Zend Framework Manual

Zend Framework手册 中文版
Zend Framework简介

Table of Contents
  • Zend Framework简介
    • 概述
    • 安装
  • Learning Zend Framework
    • Zend Framework Quick Start
    • Autoloading in Zend Framework
    • Plugins in Zend Framework
    • Getting Started with Zend_Layout
    • Getting Started Zend_View Placeholders
    • Understanding and Using Zend Form Decorators
    • Getting Started with Zend_Session, Zend_Auth, and Zend_Acl
    • Getting Started with Zend_Search_Lucene
    • Getting Started with Zend_Paginator
  • Zend Framework Reference
    • Zend_Acl
    • Zend_Amf
    • Zend_Application
    • Zend_Auth
    • Zend_Barcode
    • Zend_Cache
    • Zend_Captcha
    • Zend_CodeGenerator
    • Zend_Config
    • Zend_Config_Writer
    • Zend_Console_Getopt
    • Zend_Controller
    • Zend_Currency
    • Zend_Date
    • Zend_Db
    • Zend_Debug
    • Zend_Dojo
    • Zend_Dom
    • Zend_Exception
    • Zend_Feed
    • Zend_File
    • Zend_Filter
    • Zend_Form
    • Zend_Gdata
    • Zend_Http
    • Zend_InfoCard
    • Zend_Json
    • Zend_Layout
    • Zend_Ldap
    • Zend_Loader
    • Zend_Locale
    • Zend_Log
    • Zend_Mail
    • Zend_Markup
    • Zend_Measure
    • Zend_Memory
    • Zend_Mime
    • Zend_Navigation
    • Zend_Oauth
    • Zend_OpenId
    • Zend_Paginator
    • Zend_Pdf
    • Zend_ProgressBar
    • Zend_Queue
    • Zend_Reflection
    • Zend_Registry
    • Zend_Rest
    • Zend_Search_Lucene
    • Zend_Serializer
    • Zend_Server
    • Zend_Service
    • Zend_Session
    • Zend_Soap
    • Zend_Tag
    • Zend_Test
    • Zend_Text
    • Zend_TimeSync
    • Zend_Tool
    • Zend_Tool_Framework
    • Zend_Tool_Project
    • Zend_Translate
    • Zend_Uri
    • Zend_Validate
    • Zend_Version
    • Zend_View
    • Zend_Wildfire
    • Zend_XmlRpc
    • ZendX_Console_Process_Unix
    • ZendX_JQuery
  • 系统需求
    • PHP 版本需求
    • PHP 扩展
    • Zend Framework 组件
  • Zend Framework Migration Notes
    • Zend Framework 1.10
    • Zend Framework 1.9
    • Zend Framework 1.8
    • Zend Framework 1.7
    • Zend Framework 1.6
    • Zend Framework 1.5
    • Zend Framework 1.0
    • Zend Framework 0.9
    • Zend Framework 0.8
    • Zend Framework 0.6
  • Zend Framework 的 PHP 编码标准
    • 绪论
    • PHP File 文件格式
    • 命名约定
    • 编码风格
  • Zend Framework Documentation Standard
    • Overview
    • Documentation File Formatting
    • Recommendations
  • Recommended Project Structure for Zend Framework MVC Applications
    • Overview
    • Recommended Project Directory Structure
    • Module Structure
    • Rewrite Configuration Guide
  • Zend Framework Performance Guide
    • 介绍
    • Class Loading
    • Zend_Db Performance
    • Internationalization (i18n) and Localization (l10n)
    • View Rendering
  • 版权信息
Zend Framework

Zend Framework手册 中文版

© 2005- Zend Technologies Inc. (http://www.zend.com)
Zend Framework手册 中文版
Zend Framework简介
  • Zend Framework手册 中文版


Zend Framework简介 - Zend Framework Manual

概述

Zend Framework简介

Table of Contents
  • 概述
  • 安装
Zend Framework手册 中文版
Zend Framework手册 中文版
Zend Framework手册 中文版
概述
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework简介
  • Learning Zend Framework
  • Zend Framework Reference
  • 系统需求
  • Zend Framework Migration Notes
  • Zend Framework 的 PHP 编码标准
  • Zend Framework Documentation Standard
  • Recommended Project Structure for Zend Framework MVC Applications
  • Zend Framework Performance Guide
  • 版权信息


安装 - Zend Framework Manual

概述
Zend Framework简介
Zend Framework手册 中文版
Learning Zend Framework

安装

Zend Framework 要求 PHP版本不低于5.1.4，但强烈建议使用 5.2.3 或更高版本，因为在这两个版本之间有 许多重大安全和性能方面的改善和提高。请查阅 附录 需求 了解更多信息。

安装 Zend Framework 非常简单。只要你下载并解压它，并把发行版里的 /library 文件夹加到你的 include 路径里就行了。 你也可以把 library 文件夹移动到其它可共享的位置。

  • » 下载最新的稳定版本。 这个版本有 .zip 和 .tar.gz 两种格式，对于 Zend Framework 的新手来说是不错的选择。

  • » 下载最新的每日快照（nightly snapshot）。 对于用于勇于面对困难的人更加适用。每日快照可以体现出 Zend Framework 的开发进展。 快照同时含有英文版本和其他可用语言的文档。 如果希望使用最新的 Zend Framework 进行开发，请使用 SVN （Subversion）客户端下载最新的代码。

  • 使用 » Subversion（SVN）客户端。Zend Framework 是开源软件，开发所使用的 Subversionu 仓库也是可公开访问的。如果已经在开发中使用了 SVN 的代码， 或者希望对框架有所贡献，或者想使用比公开发布版本更新的代码，则可以考虑从 SVN 中获得 Zend Framework。

    » 导出 功能可以获得在工作目录中没有 .svn 文件夹的指定版本的框架副本。

    » 检出 对于向 Zend Framework 进行贡献是很方便的，同时工作副本可以在任何时候使用 » 提交来更新。

    » 外部定义 可以让开发者在他们的应用中方便的使用 SVN 同步框架版本。

    Zend Framework 的 SVN 仓库 URL 地址是： » http://framework.zend.com/svn/framework/standard/trunk

当拥有了一个可用的 Zend Framework 副本时，应用程序需要能够访问到框架中的类。虽然有 » 许多的方法来达到这个目的，PHP 的 » include_path 必须含有 Zend Framework 库的路径。

Zend 提供了 » 快速入门指南 可以让你尽快入门。 这是一个极好的用实际的例子来学习 Zend Framework的方法。

因为 Zend Framework 的组件是松耦合的， 在你的程序里可以使用一些独一无二的它们的组合。 本文档下面的章节基于组件划分，全面介绍了 Zend Framework 的使用。

概述
Zend Framework简介
Zend Framework手册 中文版
Learning Zend Framework
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework简介
  • 概述
  • 安装


概述 - Zend Framework Manual

Zend Framework简介
Zend Framework简介
Zend Framework手册 中文版
安装

概述

Zend Framework (ZF) 是一个开放源代码的 PHP5 开发框架，可用于来开发 web 程序和服务。ZF 100%用面向对象代码实现。 ZF中的组件非常独立，每个组件几乎不依赖于其他组件。这样的松耦合结构可以让开发者独立使用组件。 我们常称此为 “use-at-will”设计。

ZF中的组件可以独立使用，但如果将它们组合起来，就形成了一个强大而可扩展的web开发框架。 ZF 提供了强壮而高效的 MVC 实现，易于使用的数据库摘要和实现 HTML 表单解析、校验和过滤的表单组件，这样 开发者可以通过这些易用的、面向对象的接口联合所有这些操作。其它组件如 Zend_Auth 和 Zend_Acl 通过通用 的证书（credential）存储提供用户认证和授权。还有其它实现的客户库来简化访问最流行的可用的 web 服务。 不论你的程序需要什么，你都可能从 Zend Framework 中找到经过全面和严格测试的组件来使用，可以极为有效地减少开发时间。

Zend Framework 项目的主要赞助者是 » Zend Technologies，但许多 其它公司也贡献了组件或重大功能。例如 Google、 Microsoft 和 StrikeIron 作为伙伴提供了 web 服务接口和其它 希望给 Zend Framework 开发者使用的技术。

没有活跃的 ZF 社区，Zend Framework 就不能交付和支持所有这些功能。社区成员包括贡献者都可以在这些地方找到： » mailing lists, » IRC channels 和其它论坛。无论你有什么关于 ZF 的问题，在社区里总能找到答案。

Zend Framework简介
Zend Framework简介
Zend Framework手册 中文版
安装
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework简介
  • 概述
  • 安装


Learning Zend Framework - Zend Framework Manual

安装
Zend Framework Quick Start

Learning Zend Framework

Table of Contents
  • Zend Framework Quick Start
    • Zend Framework & MVC Introduction
    • Create Your Project
    • Create A Layout
    • Create a Model and Database Table
    • Create A Form
    • Congratulations!
  • Autoloading in Zend Framework
    • Introduction
    • Goals and Design
    • Basic Autoloader Usage
    • Resource Autoloading
    • Conclusion
  • Plugins in Zend Framework
    • Introduction
    • Using Plugins
    • Conclusion
  • Getting Started with Zend_Layout
    • Introduction
    • Using Zend_Layout
    • Zend_Layout: Conclusions
  • Getting Started Zend_View Placeholders
    • Introduction
    • Basic Placeholder Usage
    • Standard Placeholders
    • View Placeholders: Conclusion
  • Understanding and Using Zend Form Decorators
    • Introduction
    • Decorator Basics
    • Layering Decorators
    • Rendering Individual Decorators
    • Creating and Rendering Composite Elements
    • Conclusion
  • Getting Started with Zend_Session, Zend_Auth, and Zend_Acl
    • Building Multi-User Applications With Zend Framework
    • Managing User Sessions In ZF
    • Authenticating Users in Zend Framework
    • Building an Authorization System in Zend Framework
  • Getting Started with Zend_Search_Lucene
    • Zend_Search_Lucene Introduction
    • Lucene Index Structure
    • Index Opening and Creation
    • Indexing
    • Searching
    • Supported queries
    • Search result pagination
  • Getting Started with Zend_Paginator
    • Introduction
    • Simple Examples
    • Pagination Control and ScrollingStyles
    • Putting it all Together
安装
Zend Framework手册 中文版
Zend Framework手册 中文版
Zend Framework Quick Start
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework简介
  • Learning Zend Framework
  • Zend Framework Reference
  • 系统需求
  • Zend Framework Migration Notes
  • Zend Framework 的 PHP 编码标准
  • Zend Framework Documentation Standard
  • Recommended Project Structure for Zend Framework MVC Applications
  • Zend Framework Performance Guide
  • 版权信息


Zend Framework Quick Start - Zend Framework Manual

Learning Zend Framework
Learning Zend Framework
Zend Framework手册 中文版
Zend Framework & MVC Introduction

Zend Framework Quick Start

Table of Contents
  • Zend Framework & MVC Introduction
  • Create Your Project
  • Create A Layout
  • Create a Model and Database Table
  • Create A Form
  • Congratulations!
Learning Zend Framework
Learning Zend Framework
Zend Framework手册 中文版
Zend Framework & MVC Introduction
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Zend Framework Quick Start
  • Autoloading in Zend Framework
  • Plugins in Zend Framework
  • Getting Started with Zend_Layout
  • Getting Started Zend_View Placeholders
  • Understanding and Using Zend Form Decorators
  • Getting Started with Zend_Session, Zend_Auth, and Zend_Acl
  • Getting Started with Zend_Search_Lucene
  • Getting Started with Zend_Paginator


Zend Framework & MVC Introduction - Zend Framework Manual

Zend Framework Quick Start
Zend Framework Quick Start
Zend Framework手册 中文版
Create Your Project

Zend Framework & MVC Introduction

Zend Framework

Zend Framework is an open source, object oriented web application framework for PHP 5. Zend Framework is often called a 'component library', because it has many loosely coupled components that you can use more or less independently. But Zend Framework also provides an advanced Model-View-Controller (MVC) implementation that can be used to establish a basic structure for your Zend Framework applications. A full list of Zend Framework components along with short descriptions may be found in the » components overview. This QuickStart will introduce you to some of Zend Framework's most commonly used components, including Zend_Controller, Zend_Layout, Zend_Config, Zend_Db, Zend_Db_Table, Zend_Registry, along with a few view helpers.

Using these components, we will build a simple database-driven guest book application within minutes. The complete source code for this application is available in the following archives:

  • » zip

  • » tar.gz

Model-View-Controller

So what exactly is this MVC pattern everyone keeps talking about, and why should you care? MVC is much more than just a three-letter acronym (TLA) that you can whip out anytime you want to sound smart; it has become something of a standard in the design of modern web applications. And for good reason. Most web application code falls under one of the following three categories: presentation, business logic, and data access. The MVC pattern models this separation of concerns well. The end result is that your presentation code can be consolidated in one part of your application with your business logic in another and your data access code in yet another. Many developers have found this well-defined separation indispensable for keeping their code organized, especially when more than one developer is working on the same application.

Note: More Information
 Let's break down the pattern and take a look at the individual pieces:
< class="inlinemediaobject">

  • Model - This is the part of your application that defines its basic functionality behind a set of abstractions. Data access routines and some business logic can be defined in the model.

  • View - Views define exactly what is presented to the user. Usually controllers pass data to each view to render in some format. Views will often collect data from the user, as well. This is where you're likely to find HTML markup in your MVC applications.

  • Controller - Controllers bind the whole pattern together. They manipulate models, decide which view to display based on the user's request and other factors, pass along the data that each view will need, or hand off control to another controller entirely. Most MVC experts recommend » keeping controllers as skinny as possible.

Of course there is » more to be said about this critical pattern, but this should give you enough background to understand the guestbook application we'll be building.

Zend Framework Quick Start
Zend Framework Quick Start
Zend Framework手册 中文版
Create Your Project
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Zend Framework Quick Start
  • Zend Framework & MVC Introduction
  • Create Your Project
  • Create A Layout
  • Create a Model and Database Table
  • Create A Form
  • Congratulations!


Create Your Project - Zend Framework Manual

Zend Framework & MVC Introduction
Zend Framework Quick Start
Zend Framework手册 中文版
Create A Layout

Create Your Project

In order to create your project, you must first download and extract Zend Framework.

Install Zend Framework

The easiest way to get Zend Framework along with a complete PHP stack is by installing » Zend Server. Zend Server has native installers for Mac OSX, Windows, Fedora Core, and Ubuntu, as well as a universal installation package compatible with most Linux distributions.

After you have installed Zend Server, the Framework files may be found under /usr/local/zend/share/ZendFramework on Mac OSX and Linux, and C:\Program Files\Zend\ZendServer\share\ZendFramework on Windows. The include_path will already be configured to include Zend Framework.

Alternately, you can » Download the latest version of Zend Framework and extract the contents; make a note of where you have done so.

Optionally, you can add the path to the library/ subdirectory of the archive to your php.ini's include_path setting.

That's it! Zend Framework is now installed and ready to use.

Create Your Project

Note: zf Command Line Tool
 In your Zend Framework installation is a bin/ subdirectory, containing the scripts zf.sh and zf.bat for Unix-based and Windows-based users, respectively. Make a note of the absolute path to this script.
Wherever you see references to zf.sh or zf.bat, please substitute the absolute path to the script. On Unix-like systems, you may want to use your shell's alias functionality: alias zf.sh=path/to/ZendFramework/bin/zf.sh.
If you have problems setting up the zf command-line tool, please refer to the manual.

Open a terminal (in Windows, Start -> Run, and then use cmd). Navigate to a directory where you would like to start a project. Then, use the path to the appropriate script, and execute one of the following:

  1. # Unix:
  2. % zf.sh create project quickstart
  3.
  4. # DOS/Windows:
  5. C:> zf.bat create project quickstart

Running this command will create your basic site structure, including your initial controllers and views. The tree looks like the following:

  1. quickstart
  2. |-- application
  3. |   |-- Bootstrap.php
  4. |   |-- configs
  5. |   |   `-- application.ini
  6. |   |-- controllers
  7. |   |   |-- ErrorController.php
  8. |   |   `-- IndexController.php
  9. |   |-- models
  10. |   `-- views
  11. |       |-- helpers
  12. |       `-- scripts
  13. |           |-- error
  14. |           |   `-- error.phtml
  15. |           `-- index
  16. |               `-- index.phtml
  17. |-- library
  18. |-- public
  19. |   `-- index.php
  20. `-- tests
  21.     |-- application
  22.     |   `-- bootstrap.php
  23.     |-- library
  24.     |   `-- bootstrap.php
  25.     `-- phpunit.xml

At this point, if you haven't added Zend Framework to your include_path, we recommend either copying or symlinking it into your library/ directory. In either case, you'll want to either recursively copy or symlink the library/Zend/ directory of your Zend Framework installation into the library/ directory of your project. On unix-like systems, that would look like one of the following:

  1. # Symlink:
  2. % cd library; ln -s path/to/ZendFramework/library/Zend .
  3.
  4. # Copy:
  5. % cd library; cp -r path/to/ZendFramework/library/Zend .

On Windows systems, it may be easiest to do this from the Explorer.

Now that the project is created, the main artifacts to begin understanding are the bootstrap, configuration, action controllers, and views.

The Bootstrap

Your Bootstrap class defines what resources and components to initialize. By default, Zend Framework's Front Controller is initialized, and it uses the application/controllers/ as the default directory in which to look for action controllers (more on that later). The class looks like the following:

  1. // application/Bootstrap.php
  2.
  3. class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
  4. {
  5. }

As you can see, not much is necessary to begin with.

Configuration

While Zend Framework is itself configurationless, you often need to configure your application. The default configuration is placed in application/configs/application.ini, and contains some basic directives for setting your PHP environment (for instance, turning error reporting on and off), indicating the path to your bootstrap class (as well as its class name), and the path to your action controllers. It looks as follows:

  1. ; application/configs/application.ini
  2.
  3. [production]
  4. phpSettings.display_startup_errors = 0
  5. phpSettings.display_errors = 0
  6. includePaths.library = APPLICATION_PATH "/../library"
  7. bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
  8. bootstrap.class = "Bootstrap"
  9. resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"
  10.
  11. [staging : production]
  12.
  13. [testing : production]
  14. phpSettings.display_startup_errors = 1
  15. phpSettings.display_errors = 1
  16.
  17. [development : production]
  18. phpSettings.display_startup_errors = 1
  19. phpSettings.display_errors = 1

Several things about this file should be noted. First, when using INI-style configuration, you can reference constants directly and expand them; APPLICATION_PATH is actually a constant. Additionally note that there are several sections defined: production, staging, testing, and development. The latter three inherit settings from the "production" environment. This is a useful way to organize configuration to ensure that appropriate settings are available in each stage of application development.

Action Controllers

Your application's action controllers contain your application workflow, and do the work of mapping your requests to the appropriate models and views.

An action controller should have one or more methods ending in "Action"; these methods may then be requested via the web. By default, Zend Framework URLs follow the schema /controller/action, where "controller" maps to the action controller name (minus the "Controller" suffix) and "action" maps to an action method (minus the "Action" suffix).

Typically, you always need an IndexController, which is a fallback controller and which also serves the home page of the site, and an ErrorController, which is used to indicate things such as HTTP 404 errors (controller or action not found) and HTTP 500 errors (application errors).

The default IndexController is as follows:

  1. // application/controllers/IndexController.php
  2.
  3. class IndexController extends Zend_Controller_Action
  4. {
  5.
  6.     public function init()
  7.     {
  8.         /* Initialize action controller here */
  9.     }
  10.
  11.     public function indexAction()
  12.     {
  13.         // action body
  14.     }
  15. }

And the default ErrorController is as follows:

  1. // application/controllers/ErrorController.php
  2.
  3. class ErrorController extends Zend_Controller_Action
  4. {
  5.
  6.     public function errorAction()
  7.     {
  8.         $errors = $this->_getParam('error_handler');
  9.
  10.         switch ($errors->type) {
  11.             case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ROUTE:
  12.             case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER:
  13.             case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION:
  14.
  15.                 // 404 error -- controller or action not found
  16.                 $this->getResponse()->setHttpResponseCode(404);
  17.                 $this->view->message = 'Page not found';
  18.                 break;
  19.             default:
  20.                 // application error
  21.                 $this->getResponse()->setHttpResponseCode(500);
  22.                 $this->view->message = 'Application error';
  23.                 break;
  24.         }
  25.
  26.         $this->view->exception = $errors->exception;
  27.         $this->view->request   = $errors->request;
  28.     }
  29. }

You'll note that (1) the IndexController contains no real code, and (2) the ErrorController makes reference to a "view" property. That leads nicely into our next subject.

Views

Views in Zend Framework are written in plain old PHP. View scripts are placed in application/views/scripts/, where they are further categorized using the controller names. In our case, we have an IndexController and an ErrorController, and thus we have corresponding index/ and error/ subdirectories within our view scripts directory. Within these subdirectories, you will then find and create view scripts that correspond to each controller action exposed; in the default case, we thus have the view scripts index/index.phtml and error/error.phtml.

View scripts may contain any markup you want, and use the <?php opening tag and ?> closing tag to insert PHP directives.

The following is what we install by default for the index/index.phtml view script:

  1. <!-- application/views/scripts/index/index.phtml -->
  2. <style>
  3.
  4.     a:link,
  5.     a:visited
  6.     {
  7.         color: #0398CA;
  8.     }
  9.
  10.     span#zf-name
  11.     {
  12.         color: #91BE3F;
  13.     }
  14.
  15.     div#welcome
  16.     {
  17.         color: #FFFFFF;
  18.         background-image: url(http://framework.zend.com/images/bkg_header.jpg);
  19.         width:  600px;
  20.         height: 400px;
  21.         border: 2px solid #444444;
  22.         overflow: hidden;
  23.         text-align: center;
  24.     }
  25.
  26.     div#more-information
  27.     {
  28.         background-image: url(http://framework.zend.com/images/bkg_body-bottom.gif);
  29.         height: 100%;
  30.     }
  31.
  32. </style>
  33. <div id="welcome">
  34.     <h1>Welcome to the <span id="zf-name">Zend Framework!</span><h1 />
  35.     <h3>This is your project's main page<h3 />
  36.     <div id="more-information">
  37.         <p>
  38.             <img src="http://framework.zend.com/images/PoweredBy_ZF_4LightBG.png" />
  39.         </p>
  40.
  41.         <p>
  42.             Helpful Links: <br />
  43.             <a href="http://framework.zend.com/">Zend Framework Website</a> |
  44.             <a href="http://framework.zend.com/manual/en/">Zend Framework
  45.                 Manual</a>
  46.         </p>
  47.     </div>
  48. </div>

The error/error.phtml view script is slightly more interesting as it uses some PHP conditionals:

  1. <!-- application/views/scripts/error/error.phtml -->
  2. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN";
  3.     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd>
  4. <html xmlns="http://www.w3.org/1999/xhtml">
  5. <head>
  6.   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  7.   <title>Zend Framework Default Application</title>
  8. </head>
  9. <body>
  10.   <h1>An error occurred</h1>
  11.   <h2><?php echo $this->message ?></h2>
  12.
  13.   <?php if ('development' == $this->env): ?>
  14.
  15.   <h3>Exception information:</h3>
  16.   <p>
  17.       <b>Message:</b> <?php echo $this->exception->getMessage() ?>
  18.   </p>
  19.
  20.   <h3>Stack trace:</h3>
  21.   <pre><?php echo $this->exception->getTraceAsString() ?>
  22.   </pre>
  23.
  24.   <h3>Request Parameters:</h3>
  25.   <pre><?php echo var_export($this->request->getParams(), 1) ?>
  26.   </pre>
  27.   <?php endif ?>
  28.
  29. </body>
  30. </html>

Checkpoint

At this point, you should be able to fire up your initial Zend Framework application. Create a virtual host in your web server, and point its document root to your application's public/ subdirectory. Make sure your host's name is in your DNS or hosts file, and then point your browser to it. You should be able to see a welcome page at this point.

Zend Framework & MVC Introduction
Zend Framework Quick Start
Zend Framework手册 中文版
Create A Layout
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Zend Framework Quick Start
  • Zend Framework & MVC Introduction
  • Create Your Project
  • Create A Layout
  • Create a Model and Database Table
  • Create A Form
  • Congratulations!


Create A Layout - Zend Framework Manual

Create Your Project
Zend Framework Quick Start
Zend Framework手册 中文版
Create a Model and Database Table

Create A Layout

You may have noticed that the view scripts in the previous sections were HTML fragments- not complete pages. This is by design; we want our actions to return content only related to the action itself, not the application as a whole.

Now we must compose that generated content into a full HTML page. We'd also like to have a consistent look and feel for the application. We will use a global site layout to accomplish both of these tasks.

There are two design patterns that Zend Framework uses to implement layouts: » Two Step View and » Composite View. Two Step View is usually associated with the » Transform View pattern; the basic idea is that your application view creates a representation that is then injected into the master view for final transformation. The Composite View pattern deals with a view made of one or more atomic, application views.

In Zend Framework, Zend_Layout combines the ideas behind these patterns. Instead of each action view script needing to include site-wide artifacts, they can simply focus on their own responsibilities.

Occasionally, however, you may need application-specific information in your site-wide view script. Fortunately, Zend Framework provides a variety of view placeholders to allow you to provide such information from your action view scripts.

To get started using Zend_Layout, first we need to inform our bootstrap to use the Layout resource. This can be done by adding the following line to your application/configs/application.ini file, within the production section:

  1. ; application/configs/application.ini
  2.
  3. ; Add to [production] section:
  4. resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts"

The final INI file should look as follows:

  1. ; application/configs/application.ini
  2.
  3. [production]
  4. ; PHP settings we want to initialize
  5. phpSettings.display_startup_errors = 0
  6. phpSettings.display_errors = 0
  7. includePaths.library = APPLICATION_PATH "/../library"
  8. bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
  9. bootstrap.class = "Bootstrap"
  10. resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"
  11. resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts"
  12.
  13. [staging : production]
  14.
  15. [testing : production]
  16. phpSettings.display_startup_errors = 1
  17. phpSettings.display_errors = 1
  18.
  19. [development : production]
  20. phpSettings.display_startup_errors = 1
  21. phpSettings.display_errors = 1

This directive tells your application to look for layout view scripts in application/layouts/scripts. Create those directories now.

We also want to ensure we have an XHTML DocType declaration for our application. To enable this, we need to add a resource to our bootstrap.

The simplest way to add a bootstrap resource is to simply create a protected method beginning with the phrase _init. In this case, we want to initialize the doctype, so we'll create an _initDoctype() method within our bootstrap class:

  1. // application/Bootstrap.php
  2.
  3. class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
  4. {
  5.     protected function _initDoctype()
  6.     {
  7.     }
  8. }

Within that method, we need to hint to the view to use the appropriate doctype. But where will the view object come from? The easy solution is to initialize the View resource; once we have, we can pull the view object from the bootstrap and use it.

To initialize the view resource, add the following line to your application/configs/application.ini file, in the section marked production:

  1. ; application/configs/application.ini
  2.
  3. ; Add to [production] section:
  4. resources.view[] =

This tells us to initialize the view with no options (the '[]' indicates that the "view" key is an array, and we pass nothing to it).

Now that we have a view, let's flesh out our _initDoctype() method. In it, we will first ensure the View resource has run, fetch the view object, and then configure it:

  1. // application/Bootstrap.php
  2.
  3. class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
  4. {
  5.     protected function _initDoctype()
  6.     {
  7.         $this->bootstrap('view');
  8.         $view = $this->getResource('view');
  9.         $view->doctype('XHTML1_STRICT');
  10.     }
  11. }

Now that we've initialized Zend_Layout and set the Doctype, let's create our site-wide layout:

  1. // application/layouts/scripts/layout.phtml
  2.
  3. echo $this->doctype() ?>
  4. <html xmlns="http://www.w3.org/1999/xhtml">
  5. <head>
  6.   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  7.   <title>Zend Framework Quickstart Application</title>
  8.   <?php echo $this->headLink()->appendStylesheet('/css/global.css') ?>
  9. </head>
  10. <body>
  11. <div id="header" style="background-color: #EEEEEE; height: 30px;">
  12.     <div id="header-logo" style="float: left">
  13.         <b>ZF Quickstart Application</b>
  14.     </div>
  15.     <div id="header-navigation" style="float: right">
  16.         <a href="<?php echo $this->url(
  17.             array('controller'=>'guestbook'),
  18.             'default',
  19.             true) ?>">Guestbook</a>
  20.     </div>
  21. </div>
  22.
  23. <?php echo $this->layout()->content ?>
  24.
  25. </body>
  26. </html>

We grab our application content using the layout() view helper, and accessing the "content" key. You may render to other response segments if you wish to, but in most cases, this is all that's necessary.

Note also the use of the headLink() placeholder. This is an easy way to generate the HTML for <link> elements, as well as to keep track of them throughout your application. If you need to add additional CSS sheets to support a single action, you can do so, and be assured it will be present in the final rendered page.

Note: Checkpoint
 Now go to "http://localhost" and check out the source. You should see your XHTML header, head, title, and body sections.

Create Your Project
Zend Framework Quick Start
Zend Framework手册 中文版
Create a Model and Database Table
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Zend Framework Quick Start
  • Zend Framework & MVC Introduction
  • Create Your Project
  • Create A Layout
  • Create a Model and Database Table
  • Create A Form
  • Congratulations!


Create a Model and Database Table - Zend Framework Manual

Create A Layout
Zend Framework Quick Start
Zend Framework手册 中文版
Create A Form

Create a Model and Database Table

Before we get started, let's consider something: where will these classes live, and how will we find them? The default project we created instantiates an autoloader. We can attach other autoloaders to it so that it knows where to find different classes. Typically, we want our various MVC classes grouped under the same tree -- in this case, application/ -- and most often using a common prefix.

Zend_Controller_Front has a notion of "modules", which are individual mini-applications. Modules mimic the directory structure that the zf tool sets up under application/, and all classes inside them are assumed to begin with a common prefix, the module name. application/ is itself a module -- the "default" or "application" module. As such, we'll want to setup autoloading for resources within this directory.

Zend_Application_Module_Autoloader provides the functionality needed to map the various resources under a module to the appropriate directories, and provides a standard naming mechanism as well. An instance of the class is created by default during initialization of the bootstrap object; your application bootstrap will be default use the module prefix "Application". As such, our models, forms, and table classes will all begin with the class prefix "Application_".

Now, let's consider what makes up a guestbook. Typically, they are simply a list of entries with a comment, timestamp, and, often, email address. Assuming we store them in a database, we may also want a unique identifier for each entry. We'll likely want to be able to save an entry, fetch individual entries, and retrieve all entries. As such, a simple guestbook model API might look something like this:

  1. // application/models/Guestbook.php
  2.
  3. class Application_Model_Guestbook
  4. {
  5.     protected $_comment;
  6.     protected $_created;
  7.     protected $_email;
  8.     protected $_id;
  9.
  10.     public function __set($name, $value);
  11.     public function __get($name);
  12.
  13.     public function setComment($text);
  14.     public function getComment();
  15.
  16.     public function setEmail($email);
  17.     public function getEmail();
  18.
  19.     public function setCreated($ts);
  20.     public function getCreated();
  21.
  22.     public function setId($id);
  23.     public function getId();
  24.
  25.     public function save();
  26.     public function find($id);
  27.     public function fetchAll();
  28. }

__get() and __set() will provide a convenience mechanism for us to access the individual entry properties, and proxy to the other getters and setters. They also will help ensure that only properties we whitelist will be available in the object.

find() and fetchAll() provide the ability to fetch a single entry or all entries.

Now from here, we can start thinking about setting up our database.

First we need to initialize our Db resource. As with the Layout and View resource, we can provide configuration for the Db resource. In your application/configs/application.ini file, add the following lines in the appropriate sections.

  1. ; application/configs/application.ini
  2.
  3. ; Add these lines to the appropriate sections:
  4. [production]
  5. resources.db.adapter       = "PDO_SQLITE"
  6. resources.db.params.dbname = APPLICATION_PATH "/../data/db/guestbook.db"
  7.
  8. [testing : production]
  9. resources.db.params.dbname = APPLICATION_PATH "/../data/db/guestbook-testing.db"
  10.
  11. [development : production]
  12. resources.db.params.dbname = APPLICATION_PATH "/../data/db/guestbook-dev.db"

Your final configuration file should look like the following:

  1. ; application/configs/application.ini
  2.
  3. [production]
  4. phpSettings.display_startup_errors = 0
  5. phpSettings.display_errors = 0
  6. bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
  7. bootstrap.class = "Bootstrap"
  8. resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"
  9. resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts"
  10. resources.view[] =
  11. resources.db.adapter = "PDO_SQLITE"
  12. resources.db.params.dbname = APPLICATION_PATH "/../data/db/guestbook.db"
  13.
  14. [staging : production]
  15.
  16. [testing : production]
  17. phpSettings.display_startup_errors = 1
  18. phpSettings.display_errors = 1
  19. resources.db.params.dbname = APPLICATION_PATH "/../data/db/guestbook-testing.db"
  20.
  21. [development : production]
  22. phpSettings.display_startup_errors = 1
  23. phpSettings.display_errors = 1
  24. resources.db.params.dbname = APPLICATION_PATH "/../data/db/guestbook-dev.db"

Note that the database(s) will be stored in data/db/. Create those directories, and make them world-writeable. On unix-like systems, you can do that as follows:

  1. % mkdir -p data/db; chmod -R a+rwX data

On Windows, you will need to create the directories in Explorer and set the permissions to allow anyone to write to the directory.

At this point we have a connection to a database; in our case, its a connection to a Sqlite database located inside our application/data/ directory. So, let's design a simple table that will hold our guestbook entries.

  1. -- scripts/schema.sqlite.sql
  2. --
  3. -- You will need load your database schema with this SQL.
  4.
  5. CREATE TABLE guestbook (
  6.     id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
  7.     email VARCHAR(32) NOT NULL DEFAULT 'noemail@test.com',
  8.     comment TEXT NULL,
  9.     created DATETIME NOT NULL
  10. );
  11.
  12. CREATE INDEX "id" ON "guestbook" ("id");

And, so that we can have some working data out of the box, lets create a few rows of information to make our application interesting.

  1. -- scripts/data.sqlite.sql
  2. --
  3. -- You can begin populating the database with the following SQL statements.
  4.
  5. INSERT INTO guestbook (email, comment, created) VALUES
  6.     ('ralph.schindler@zend.com',
  7.     'Hello! Hope you enjoy this sample zf application!',
  8.     DATETIME('NOW'));
  9. INSERT INTO guestbook (email, comment, created) VALUES
  10.     ('foo@bar.com',
  11.     'Baz baz baz, baz baz Baz baz baz - baz baz baz.',
  12.     DATETIME('NOW'));

Now that we have both the schema and some data defined. Lets get a script together that we can now execute to build this database. Naturally, this is not needed in production, but this script will help developers build out the database requirements locally so they can have the fully working application. Create the script as scripts/load.sqlite.php with the following contents:

  1. // scripts/load.sqlite.php
  2.
  3. /**
  4. * Script for creating and loading database
  5. */
  6.
  7. // Initialize the application path and autoloading
  8. defined('APPLICATION_PATH')
  9.     || define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application'));
  10. set_include_path(implode(PATH_SEPARATOR, array(
  11.     APPLICATION_PATH . '/../library',
  12.     get_include_path(),
  13. )));
  14. require_once 'Zend/Loader/Autoloader.php';
  15. Zend_Loader_Autoloader::getInstance();
  16.
  17. // Define some CLI options
  18. $getopt = new Zend_Console_Getopt(array(
  19.     'withdata|w' => 'Load database with sample data',
  20.     'env|e-s'    => 'Application environment for which to create database (defaults to development)',
  21.     'help|h'     => 'Help -- usage message',
  22. ));
  23. try {
  24.     $getopt->parse();
  25. } catch (Zend_Console_Getopt_Exception $e) {
  26.     // Bad options passed: report usage
  27.     echo $e->getUsageMessage();
  28.     return false;
  29. }
  30.
  31. // If help requested, report usage message
  32. if ($getopt->getOption('h')) {
  33.     echo $getopt->getUsageMessage();
  34.     return true;
  35. }
  36.
  37. // Initialize values based on presence or absence of CLI options
  38. $withData = $getopt->getOption('w');
  39. $env      = $getopt->getOption('e');
  40. defined('APPLICATION_ENV')
  41.     || define('APPLICATION_ENV', (null === $env) ? 'development' : $env);
  42.
  43. // Initialize Zend_Application
  44. $application = new Zend_Application(
  45.     APPLICATION_ENV,
  46.     APPLICATION_PATH . '/configs/application.ini'
  47. );
  48.
  49. // Initialize and retrieve DB resource
  50. $bootstrap = $application->getBootstrap();
  51. $bootstrap->bootstrap('db');
  52. $dbAdapter = $bootstrap->getResource('db');
  53.
  54. // let the user know whats going on (we are actually creating a
  55. // database here)
  56. if ('testing' != APPLICATION_ENV) {
  57.     echo 'Writing Database Guestbook in (control-c to cancel): ' . PHP_EOL;
  58.     for ($x = 5; $x > 0; $x--) {
  59.         echo $x . "\r"; sleep(1);
  60.     }
  61. }
  62.
  63. // Check to see if we have a database file already
  64. $options = $bootstrap->getOption('resources');
  65. $dbFile  = $options['db']['params']['dbname'];
  66. if (file_exists($dbFile)) {
  67.     unlink($dbFile);
  68. }
  69.
  70. // this block executes the actual statements that were loaded from
  71. // the schema file.
  72. try {
  73.     $schemaSql = file_get_contents(dirname(__FILE__) . '/schema.sqlite.sql');
  74.     // use the connection directly to load sql in batches
  75.     $dbAdapter->getConnection()->exec($schemaSql);
  76.     chmod($dbFile, 0666);
  77.
  78.     if ('testing' != APPLICATION_ENV) {
  79.         echo PHP_EOL;
  80.         echo 'Database Created';
  81.         echo PHP_EOL;
  82.     }
  83.
  84.     if ($withData) {
  85.         $dataSql = file_get_contents(dirname(__FILE__) . '/data.sqlite.sql');
  86.         // use the connection directly to load sql in batches
  87.         $dbAdapter->getConnection()->exec($dataSql);
  88.         if ('testing' != APPLICATION_ENV) {
  89.             echo 'Data Loaded.';
  90.             echo PHP_EOL;
  91.         }
  92.     }
  93.
  94. } catch (Exception $e) {
  95.     echo 'AN ERROR HAS OCCURED:' . PHP_EOL;
  96.     echo $e->getMessage() . PHP_EOL;
  97.     return false;
  98. }
  99.
  100. // generally speaking, this script will be run from the command line
  101. return true;

Now, let's execute this script. From a terminal or the DOS command line, do the following:

  1. % php scripts/load.sqlite.php --withdata

You should see output like the following:

  1. path/to/ZendFrameworkQuickstart/scripts$ php load.sqlite.php --withdata
  2. Writing Database Guestbook in (control-c to cancel):
  3. 1
  4. Database Created
  5. Data Loaded.

Now we have a fully working database and table for our guestbook application. Our next few steps are to build out our application code. This includes building a data source (in our case, we will use Zend_Db_Table), and a data mapper to connect that data source to our domain model. Finally we'll also create the controller that will interact with this model to both display existing entries and process new entries.

We'll use a » Table Data Gateway to connect to our data source; Zend_Db_Table provides this functionality. To get started, lets create a Zend_Db_Table-based table class. First, create the directory application/models/DbTable/. Then create and edit a file Guestbook.php within it, and add the following contents:

  1. // application/models/DbTable/Guestbook.php
  2.
  3. /**
  4. * This is the DbTable class for the guestbook table.
  5. */
  6. class Application_Model_DbTable_Guestbook extends Zend_Db_Table_Abstract
  7. {
  8.     /** Table name */
  9.     protected $_name    = 'guestbook';
  10. }

Note the class prefix: Application_Model_DbTable. The class prefix for our module, "Application", is the first segment, and then we have the component, "Model_DbTable"; the latter is mapped to the models/DbTable/ directory of the module.

All that is truly necessary when extending Zend_Db_Table is to provide a table name and optionally the primary key (if it is not "id").

Now let's create a » Data Mapper. A Data Mapper maps a domain object to the database. In our case, it will map our model, Application_Model_Guestbook, to our data source, Application_Model_DbTable_Guestbook. A typical API for a data mapper is as follows:

  1. // application/models/GuestbookMapper.php
  2.
  3. class Application_Model_GuestbookMapper
  4. {
  5.     public function save($model);
  6.     public function find($id, $model);
  7.     public function fetchAll();
  8. }

In addition to these methods, we'll add methods for setting and retrieving the Table Data Gateway. The final class, located in application/models/GuestbookMapper.php, looks like this:

  1. // application/models/GuestbookMapper.php
  2.
  3. class Application_Model_GuestbookMapper
  4. {
  5.     protected $_dbTable;
  6.
  7.     public function setDbTable($dbTable)
  8.     {
  9.         if (is_string($dbTable)) {
  10.             $dbTable = new $dbTable();
  11.         }
  12.         if (!$dbTable instanceof Zend_Db_Table_Abstract) {
  13.             throw new Exception('Invalid table data gateway provided');
  14.         }
  15.         $this->_dbTable = $dbTable;
  16.         return $this;
  17.     }
  18.
  19.     public function getDbTable()
  20.     {
  21.         if (null === $this->_dbTable) {
  22.             $this->setDbTable('Application_Model_DbTable_Guestbook');
  23.         }
  24.         return $this->_dbTable;
  25.     }
  26.
  27.     public function save(Application_Model_Guestbook $guestbook)
  28.     {
  29.         $data = array(
  30.             'email'   => $guestbook->getEmail(),
  31.             'comment' => $guestbook->getComment(),
  32.             'created' => date('Y-m-d H:i:s'),
  33.         );
  34.
  35.         if (null === ($id = $guestbook->getId())) {
  36.             unset($data['id']);
  37.             $this->getDbTable()->insert($data);
  38.         } else {
  39.             $this->getDbTable()->update($data, array('id = ?' => $id));
  40.         }
  41.     }
  42.
  43.     public function find($id, Application_Model_Guestbook $guestbook)
  44.     {
  45.         $result = $this->getDbTable()->find($id);
  46.         if (0 == count($result)) {
  47.             return;
  48.         }
  49.         $row = $result->current();
  50.         $guestbook->setId($row->id)
  51.                   ->setEmail($row->email)
  52.                   ->setComment($row->comment)
  53.                   ->setCreated($row->created);
  54.     }
  55.
  56.     public function fetchAll()
  57.     {
  58.         $resultSet = $this->getDbTable()->fetchAll();
  59.         $entries   = array();
  60.         foreach ($resultSet as $row) {
  61.             $entry = new Application_Model_Guestbook();
  62.             $entry->setId($row->id)
  63.                   ->setEmail($row->email)
  64.                   ->setComment($row->comment)
  65.                   ->setCreated($row->created)
  66.                   ->setMapper($this);
  67.             $entries[] = $entry;
  68.         }
  69.         return $entries;
  70.     }
  71. }

Now it's time to update our model class slightly, to accomodate the data mapper. Just like the data mapper contains a reference to the data source, the model contains a reference to the data mapper. Additionally, we'll make it easy to populate the model by passing an array of data either to the constructor or a setOptions() method. The final model class, located in application/models/Guestbook.php, looks like this:

  1. // application/models/Guestbook.php
  2.
  3. class Application_Model_Guestbook
  4. {
  5.     protected $_comment;
  6.     protected $_created;
  7.     protected $_email;
  8.     protected $_id;
  9.     protected $_mapper;
  10.
  11.     public function __construct(array $options = null)
  12.     {
  13.         if (is_array($options)) {
  14.             $this->setOptions($options);
  15.         }
  16.     }
  17.
  18.     public function __set($name, $value)
  19.     {
  20.         $method = 'set' . $name;
  21.         if (('mapper' == $name) || !method_exists($this, $method)) {
  22.             throw new Exception('Invalid guestbook property');
  23.         }
  24.         $this->$method($value);
  25.     }
  26.
  27.     public function __get($name)
  28.     {
  29.         $method = 'get' . $name;
  30.         if (('mapper' == $name) || !method_exists($this, $method)) {
  31.             throw new Exception('Invalid guestbook property');
  32.         }
  33.         return $this->$method();
  34.     }
  35.
  36.     public function setOptions(array $options)
  37.     {
  38.         $methods = get_class_methods($this);
  39.         foreach ($options as $key => $value) {
  40.             $method = 'set' . ucfirst($key);
  41.             if (in_array($method, $methods)) {
  42.                 $this->$method($value);
  43.             }
  44.         }
  45.         return $this;
  46.     }
  47.
  48.     public function setComment($text)
  49.     {
  50.         $this->_comment = (string) $text;
  51.         return $this;
  52.     }
  53.
  54.     public function getComment()
  55.     {
  56.         return $this->_comment;
  57.     }
  58.
  59.     public function setEmail($email)
  60.     {
  61.         $this->_email = (string) $email;
  62.         return $this;
  63.     }
  64.
  65.     public function getEmail()
  66.     {
  67.         return $this->_email;
  68.     }
  69.
  70.     public function setCreated($ts)
  71.     {
  72.         $this->_created = $ts;
  73.         return $this;
  74.     }
  75.
  76.     public function getCreated()
  77.     {
  78.         return $this->_created;
  79.     }
  80.
  81.     public function setId($id)
  82.     {
  83.         $this->_id = (int) $id;
  84.         return $this;
  85.     }
  86.
  87.     public function getId()
  88.     {
  89.         return $this->_id;
  90.     }
  91.
  92.     public function setMapper($mapper)
  93.     {
  94.         $this->_mapper = $mapper;
  95.         return $this;
  96.     }
  97.
  98.     public function getMapper()
  99.     {
  100.         if (null === $this->_mapper) {
  101.             $this->setMapper(new Application_Model_GuestbookMapper());
  102.         }
  103.         return $this->_mapper;
  104.     }
  105.
  106.     public function save()
  107.     {
  108.         $this->getMapper()->save($this);
  109.     }
  110.
  111.     public function find($id)
  112.     {
  113.         $this->getMapper()->find($id, $this);
  114.         return $this;
  115.     }
  116.
  117.     public function fetchAll()
  118.     {
  119.         return $this->getMapper()->fetchAll();
  120.     }
  121. }

Lastly, to connect these elements all together, lets create a guestbook controller that will both list the entries that are currently inside the database.

To create a new controller, open a terminal or DOS console, navigate to your project directory, and enter the following:

  1. # Unix-like systems:
  2. % zf.sh create controller guestbook
  3.
  4. # DOS/Windows:
  5. C:> zf.bat create controller guestbook

This will create a new controller, GuestbookController, in application/controllers/GuestbookController.php, with a single action method, indexAction(). It will also create a view script directory for the controller, application/views/scripts/guestbook/, with a view script for the index action.

We'll use the "index" action as a landing page to view all guestbook entries.

Now, let's flesh out the basic application logic. On a hit to indexAction(), we'll display all guestbook entries. This would look like the following:

  1. // application/controllers/GuestbookController.php
  2.
  3. class GuestbookController extends Zend_Controller_Action
  4. {
  5.     public function indexAction()
  6.     {
  7.         $guestbook = new Application_Model_Guestbook();
  8.         $this->view->entries = $guestbook->fetchAll();
  9.     }
  10. }

And, of course, we need a view script to go along with that. Edit application/views/scripts/guestbook/index.phtml to read as follows:

  1. <!-- application/views/scripts/guestbook/index.phtml -->
  2.
  3. <p><a href="<?php echo $this->url(
  4.     array(
  5.         'controller' => 'guestbook',
  6.         'action'     => 'sign'
  7.     ),
  8.     'default',
  9.     true) ?>">Sign Our Guestbook</a></p>
  10.
  11. Guestbook Entries: <br />
  12. <dl>
  13.     <?php foreach ($this->entries as $entry): ?>
  14.     <dt><?php echo $this->escape($entry->email) ?></dt>
  15.     <dd><?php echo $this->escape($entry->comment) ?></dd>
  16.     <?php endforeach ?>
  17. </dl>

Note: Checkpoint
 Now browse to "http://localhost/guestbook". You should see the following in your browser:
< class="inlinemediaobject">

Note: Using the data loader script
 The data loader script introduced in this section (scripts/load.sqlite.php) can be used to create the database for each environment you have defined, as well as to load it with sample data. Internally, it utilizes Zend_Console_Getopt, which allows it to provide a number of command line switches. If you pass the "-h" or "--help" switch, it will give you the available options:

  1. Usage: load.sqlite.php [ options ]
  2. --withdata|-w         Load database with sample data
  3. --env|-e [  ]         Application environment for which to create database
  4.                       (defaults to development)
  5. --help|-h             Help -- usage message)]]
The "-e" switch allows you to specify the value to use for the constant APPLICATION_ENV -- which in turn allows you to create a SQLite database for each environment you define. Be sure to run the script for the environment you choose for your application when deploying.

Create A Layout
Zend Framework Quick Start
Zend Framework手册 中文版
Create A Form
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Zend Framework Quick Start
  • Zend Framework & MVC Introduction
  • Create Your Project
  • Create A Layout
  • Create a Model and Database Table
  • Create A Form
  • Congratulations!


Create A Form - Zend Framework Manual

Create a Model and Database Table
Zend Framework Quick Start
Zend Framework手册 中文版
Congratulations!

Create A Form

For our guestbook to be useful, we need a form for submitting new entries.

Our first order of business is to create the actual form class. First, create the directory application/forms/. This directory will contain form classes for the application. Next, we'll create a form class in application/forms/Guestbook.php:

  1. // application/forms/Guestbook.php
  2.
  3. class Application_Form_Guestbook extends Zend_Form
  4. {
  5.     public function init()
  6.     {
  7.         // Set the method for the display form to POST
  8.         $this->setMethod('post');
  9.
  10.         // Add an email element
  11.         $this->addElement('text', 'email', array(
  12.             'label'      => 'Your email address:',
  13.             'required'   => true,
  14.             'filters'    => array('StringTrim'),
  15.             'validators' => array(
  16.                 'EmailAddress',
  17.             )
  18.         ));
  19.
  20.         // Add the comment element
  21.         $this->addElement('textarea', 'comment', array(
  22.             'label'      => 'Please Comment:',
  23.             'required'   => true,
  24.             'validators' => array(
  25.                 array('validator' => 'StringLength', 'options' => array(0, 20))
  26.                 )
  27.         ));
  28.
  29.         // Add a captcha
  30.         $this->addElement('captcha', 'captcha', array(
  31.             'label'      => 'Please enter the 5 letters displayed below:',
  32.             'required'   => true,
  33.             'captcha'    => array(
  34.                 'captcha' => 'Figlet',
  35.                 'wordLen' => 5,
  36.                 'timeout' => 300
  37.             )
  38.         ));
  39.
  40.         // Add the submit button
  41.         $this->addElement('submit', 'submit', array(
  42.             'ignore'   => true,
  43.             'label'    => 'Sign Guestbook',
  44.         ));
  45.
  46.         // And finally add some CSRF protection
  47.         $this->addElement('hash', 'csrf', array(
  48.             'ignore' => true,
  49.         ));
  50.     }
  51. }

The above form defines five elements: an email address field, a comment field, a CAPTCHA for preventing spam submissions, a submit button, and a CSRF protection token.

Next, we will add a signAction() to our GuestbookController which will process the form upon submission. To create the action and related view script, execute the following:

  1. # Unix-like systems:
  2. % zf.sh create action sign guestbook
  3.
  4. # DOS/Windows:
  5. C:> zf.bat create action sign guestbook

This will create a signAction() method in our controller, as well as the appropriate view script.

Let's add some logic into our guestbook controller's sign action. We need to first check if we're getting a POST or a GET request; in the latter case, we'll simply display the form. However, if we get a POST request, we'll want to validate the posted data against our form, and, if valid, create a new entry and save it. The logic might look like this:

  1. // application/controllers/GuestbookController.php
  2.
  3. class GuestbookController extends Zend_Controller_Action
  4. {
  5.     // snipping indexAction()...
  6.
  7.     public function signAction()
  8.     {
  9.         $request = $this->getRequest();
  10.         $form    = new Application_Form_Guestbook();
  11.
  12.         if ($this->getRequest()->isPost()) {
  13.             if ($form->isValid($request->getPost())) {
  14.                 $model = new Application_Model_Guestbook($form->getValues());
  15.                 $model->save();
  16.                 return $this->_helper->redirector('index');
  17.             }
  18.         }
  19.
  20.         $this->view->form = $form;
  21.     }
  22. }

Of course, we also need to edit the view script; edit application/views/scripts/guestbook/sign.phtml to read:

  1. <!-- application/views/scripts/guestbook/sign.phtml -->
  2.
  3. Please use the form below to sign our guestbook!
  4.
  5. <?php
  6. $this->form->setAction($this->url());
  7. echo $this->form;

Note: Better Looking Forms
 No one will be waxing poetic about the beauty of this form anytime soon. No matter - form appearance is fully customizable! See the decorators section in the reference guide for details.
Additionally, you may be interested in » this series of posts on decorators.

Note: Checkpoint
 Now browse to "http://localhost/guestbook/sign". You should see the following in your browser:
< class="inlinemediaobject">

Create a Model and Database Table
Zend Framework Quick Start
Zend Framework手册 中文版
Congratulations!
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Zend Framework Quick Start
  • Zend Framework & MVC Introduction
  • Create Your Project
  • Create A Layout
  • Create a Model and Database Table
  • Create A Form
  • Congratulations!


Congratulations! - Zend Framework Manual

Create A Form
Zend Framework Quick Start
Zend Framework手册 中文版
Autoloading in Zend Framework

Congratulations!

You have now built a very simple application using some of the most commonly used Zend Framework components. Zend Framework makes many components available to you which address most common requirements in web applications, including web services, search, PDF reading and writing, authentication, authorization, and much more. The Reference Guide is a great place to find out more about the components you've used in this QuickStart as well as other components. We hope you find Zend Framework useful and - more importantly - fun!

Create A Form
Zend Framework Quick Start
Zend Framework手册 中文版
Autoloading in Zend Framework
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Zend Framework Quick Start
  • Zend Framework & MVC Introduction
  • Create Your Project
  • Create A Layout
  • Create a Model and Database Table
  • Create A Form
  • Congratulations!


Autoloading in Zend Framework - Zend Framework Manual

Congratulations!
Learning Zend Framework
Zend Framework手册 中文版
Introduction

Autoloading in Zend Framework

Table of Contents
  • Introduction
  • Goals and Design
  • Basic Autoloader Usage
  • Resource Autoloading
  • Conclusion
Congratulations!
Learning Zend Framework
Zend Framework手册 中文版
Introduction
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Zend Framework Quick Start
  • Autoloading in Zend Framework
  • Plugins in Zend Framework
  • Getting Started with Zend_Layout
  • Getting Started Zend_View Placeholders
  • Understanding and Using Zend Form Decorators
  • Getting Started with Zend_Session, Zend_Auth, and Zend_Acl
  • Getting Started with Zend_Search_Lucene
  • Getting Started with Zend_Paginator


Introduction - Zend Framework Manual

Autoloading in Zend Framework
Autoloading in Zend Framework
Zend Framework手册 中文版
Goals and Design

Introduction

Autoloading is a mechanism that eliminates the need to manually require dependencies within your PHP code. Per » the PHP autoload manual, once an autoloader has been defined, it "is automatically called in case you are trying to use a class or an interface which hasn't been defined yet."

Using autoloading, you do not need to worry about where a class exists in your project. With well-defined autoloaders, you do not need to worry about where a class file is relative to the current class file; you simply use the class, and the autoloader will perform the file lookup.

Additionally, autoloading, because it defers loading to the last possible moment and ensures that a match only has to occur once, can be a huge performance boost -- particularly if you take the time to strip out require_once() calls before you move to deployment.

Zend Framework encourages the use of autoloading, and provides several tools to provide autoloading of both library code as well as application code. This tutorial covers these tools, as well as how to use them effectively.

Autoloading in Zend Framework
Autoloading in Zend Framework
Zend Framework手册 中文版
Goals and Design
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Autoloading in Zend Framework
  • Introduction
  • Goals and Design
  • Basic Autoloader Usage
  • Resource Autoloading
  • Conclusion


Goals and Design - Zend Framework Manual

Introduction
Autoloading in Zend Framework
Zend Framework手册 中文版
Basic Autoloader Usage

Goals and Design

Class Naming Conventions

To understand autoloading in Zend Framework, first you need to understand the relationship between class names and class files.

Zend Framework has borrowed an idea from » PEAR, whereby class names have a 1:1 relationship with the filesystem. Simply put, the underscore character ("_") is replaced by a directory separator in order to resolve the path to the file, and then the suffix ".php" is added. For example, the class "Foo_Bar_Baz" would correspond to "Foo/Bar/Baz.php" on the filesystem. The assumption is also that the classes may be resolved via PHP's include_path setting, which allows both include() and require() to find the filename via a relative path lookup on the include_path.

Additionally, per PEAR as well as the » PHP project, we use and recommend using a vendor or project prefix for your code. What this means is that all classes you write will share a common class prefix; for example, all code in Zend Framework has the prefix "Zend_". This naming convention helps prevent naming collisions. Within Zend Framework, we often refer to this as the "namespace" prefix; be careful not to confuse it with PHP's native namespace implementation.

Zend Framework follows these simple rules internally, and our coding standards encourage that you do so as well for all library code.

Autoloader Conventions and Design

Zend Framework's autoloading support, provided primarily via Zend_Loader_Autoloader, has the following goals and design elements:

  • Provide namespace matching. If the class namespace prefix is not in a list of registered namespaces, return FALSE immediately. This allows for more optimistic matching, as well as fallback to other autoloaders.

  • Allow the autoloader to act as a fallback autoloader. In the case where a team may be widely distributed, or using an undetermined set of namespace prefixes, the autoloader should still be configurable such that it will attempt to match any namespace prefix. It will be noted, however, that this practice is not recommended, as it can lead to unnecessary lookups.

  • Allow toggling error suppression. We feel -- and the greater PHP community does as well -- that error suppression is a bad idea. It's expensive, and it masks very real application problems. So, by default, it should be off. However, if a developer insists that it be on, we allow toggling it on.

  • Allow specifying custom callbacks for autoloading. Some developers don't want to use Zend_Loader::loadClass() for autoloading, but still want to make use of Zend Framework's mechanisms. Zend_Loader_Autoloader allows specyfing an alternate callback for autoloading.

  • Allow manipulation of the SPL autoload callback chain. The purpose of this is to allow specifying additional autoloaders -- for instance, resource loaders for classes that don't have a 1:1 mapping to the filesystem -- to be registered before or after the primary Zend Framework autoloader.

Introduction
Autoloading in Zend Framework
Zend Framework手册 中文版
Basic Autoloader Usage
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Autoloading in Zend Framework
  • Introduction
  • Goals and Design
  • Basic Autoloader Usage
  • Resource Autoloading
  • Conclusion


Basic Autoloader Usage - Zend Framework Manual

Goals and Design
Autoloading in Zend Framework
Zend Framework手册 中文版
Resource Autoloading

Basic Autoloader Usage

Now that we have an understanding of what autoloading is and the goals and design of Zend Framework's autoloading solution, let's look at how to use Zend_Loader_Autoloader.

In the simplest case, you would simply require the class, and then instantiate it. Since Zend_Loader_Autoloader is a singleton (due to the fact that the SPL autoloader is a single resource), we use getInstance() to retrieve an instance.

  1. require_once 'Zend/Loader/Autoloader.php';
  2. Zend_Loader_Autoloader::getInstance();

By default, this will allow loading any classes with the class namespace prefixes of "Zend_" or "ZendX_", as long as they are on your include_path.

What happens if you have other namespace prefixes you wish to use? The best, and simplest, way is to call the registerNamespace() method on the instance. You can pass a single namespace prefix, or an array of them:

  1. require_once 'Zend/Loader/Autoloader.php';
  2. $loader = Zend_Loader_Autoloader::getInstance();
  3. $loader->registerNamespace('Foo_');
  4. $loader->registerNamespace(array('Foo_', 'Bar_'));

Alternately, you can tell Zend_Loader_Autoloader to act as a "fallback" autoloader. This means that it will try to resolve any class regardless of namespace prefix.

  1. $loader->setFallbackAutoloader(true);
Warning

Do not use as a fallback autoloader

While it's tempting to use Zend_Loader_Autoloader as a fallback autoloader, we do not recommend the practice.

Internally, Zend_Loader_Autoloader uses Zend_Loader::loadClass() to load classes. That method uses include() to attempt to load the given class file. include() will return a boolean FALSE if not successful -- but also issues a PHP warning. This latter fact can lead to some issues:

  • If display_errors is enabled, the warning will be included in output.

  • Depending on the error_reporting level you have chosen, it could also clutter your logs.

You can suppress the error messages (the Zend_Loader_Autoloader documentation details this), but note that the suppression is only relevant when display_errors is enabled; the error log will always display the messages. For these reasons, we recommend always configuring the namespace prefixes the autoloader should be aware of

Note: Namespace Prefixes vs PHP Namespaces
 At the time this is written, PHP 5.3 has been released. With that version, PHP now has official namespace support.
However, Zend Framework predates PHP 5.3, and thus namespaces. Within Zend Framework, when we refer to "namespaces", we are referring to a practice whereby classes are prefixed with a vender "namespace". As an example, all Zend Framework class names are prefixed with "Zend_" -- that is our vendor "namespace".
Zend Framework plans to offer native PHP namespace support to the autoloader in future revisions, and its own library will utilize namespaces starting with version 2.0.0.

If you have a custom autoloader you wish to use with Zend Framework -- perhaps an autoloader from a third-party library you are also using -- you can manage it with Zend_Loader_Autoloader's pushAutoloader() and unshiftAutoloader() methods. These methods will append or prepend, respectively, autoloaders to a chain that is called prior to executing Zend Framework's internal autoloading mechanism. This approach offers the following benefits:

  • Each method takes an optional second argument, a class namespace prefix. This can be used to indicate that the given autoloader should only be used when looking up classes with that given class prefix. If the class being resolved does not have that prefix, the autoloader will be skipped -- which can lead to performance improvements.

  • If you need to manipulate spl_autoload()'s registry, any autoloaders that are callbacks pointing to instance methods can pose issues, as spl_autoload_functions() does not return the exact same callbacks. Zend_Loader_Autoloader has no such limitation.

Autoloaders managed this way may be any valid PHP callback.

  1. // Append function 'my_autoloader' to the stack,
  2. // to manage classes with the prefix 'My_':
  3. $loader->pushAutoloader('my_autoloader', 'My_');
  4.
  5. // Prepend static method Foo_Loader::autoload() to the stack,
  6. // to manage classes with the prefix 'Foo_':
  7. $loader->unshiftAutoloader(array('Foo_Loader', 'autoload'), 'Foo_');
Goals and Design
Autoloading in Zend Framework
Zend Framework手册 中文版
Resource Autoloading
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Autoloading in Zend Framework
  • Introduction
  • Goals and Design
  • Basic Autoloader Usage
  • Resource Autoloading
  • Conclusion


Resource Autoloading - Zend Framework Manual

Basic Autoloader Usage
Autoloading in Zend Framework
Zend Framework手册 中文版
Conclusion

Resource Autoloading

Often, when developing an application, it's either difficult to package classes in the 1:1 classname:filename standard Zend Framework recommends, or it's advantageous for purposes of packaging not to do so. However, this means you class files will not be found by the autoloader.

If you read through the design goals for the autoloader, the last point in that section indicated that the solution should cover this situation. Zend Framework does so with Zend_Loader_Autoloader_Resource.

A resource is just a name that corresponds to a component namespace (which is appended to the autoloader's namespace) and a path (which is relative to the autoloader's base path). In action, you'd do something like this:

  1. $loader = new Zend_Application_Module_Autoloader(array(
  2.     'namespace' => 'Blog',
  3.     'basePath'  => APPLICATION_PATH . '/modules/blog',
  4. ));

Once you have the loader in place, you then need to inform it of the various resource types it's aware of. These resource types are simply pairs of subtree and prefix.

As an example, consider the following tree:

  1. path/to/some/resources/
  2. |-- forms/
  3. |   `-- Guestbook.php        // Foo_Form_Guestbook
  4. |-- models/
  5. |   |-- DbTable/
  6. |   |   `-- Guestbook.php    // Foo_Model_DbTable_Guestbook
  7. |   |-- Guestbook.php        // Foo_Model_Guestbook
  8. |   `-- GuestbookMapper.php  // Foo_Model_GuestbookMapper

Our first step is creating the resource loader:

  1. $loader = new Zend_Loader_Autoloader_Resource(array(
  2.     'basePath'  => 'path/to/some/resources/',
  3.     'namespace' => 'Foo',
  4. ));

Next, we need to define some resource types. Zend_Loader_Autoloader_Resourse::addResourceType() has three arguments: the "type" of resource (an arbitrary string), the path under the base path in which the resource type may be found, and the component prefix to use for the resource type. In the above tree, we have three resource types: form (in the subdirectory "forms", with a component prefix of "Form"), model (in the subdirectory "models", with a component prefix of "Model"), and dbtable (in the subdirectory "models/DbTable", with a component prefix of "Model_DbTable"). We'd define them as follows:

  1. $loader->addResourceType('form', 'forms', 'Form')
  2.        ->addResourceType('model', 'models', 'Model')
  3.        ->addResourceType('dbtable', 'models/DbTable', 'Model_DbTable');

Once defined, we can simply use these classes:

  1. $form      = new Foo_Form_Guestbook();
  2. $guestbook = new Foo_Model_Guestbook();

Note: Module Resource Autoloading
 Zend Framework's MVC layer encourages the use of "modules", which are self-contained applications within your site. Modules typically have a number of resource types by default, and Zend Framework even recommends a standard directory layout for modules. Resource autoloaders are therefore quite useful in this paradigm -- so useful that they are enabled by default when you create a bootstrap class for your module that extends Zend_Application_Module_Bootstrap. For more information, read the Zend_Loader_Autoloader_Module documentation.

Basic Autoloader Usage
Autoloading in Zend Framework
Zend Framework手册 中文版
Conclusion
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Autoloading in Zend Framework
  • Introduction
  • Goals and Design
  • Basic Autoloader Usage
  • Resource Autoloading
  • Conclusion


Conclusion - Zend Framework Manual

Resource Autoloading
Autoloading in Zend Framework
Zend Framework手册 中文版
Plugins in Zend Framework

Conclusion

Zend Framework encourages the use of autoloading, and even initializes it by default in Zend_Application. Hopefully this tutorial provides you with the information you need to use Zend_Loader_Autoloader to its best advantage, as well as extend its capabilities by attaching custom autoloaders or resource autoloaders.

For more information on its usage, read the Zend_Loader_Autoloader and Zend_Loader_Autoloader_Resource manual pages.

Resource Autoloading
Autoloading in Zend Framework
Zend Framework手册 中文版
Plugins in Zend Framework
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Autoloading in Zend Framework
  • Introduction
  • Goals and Design
  • Basic Autoloader Usage
  • Resource Autoloading
  • Conclusion


Plugins in Zend Framework - Zend Framework Manual

Conclusion
Learning Zend Framework
Zend Framework手册 中文版
Introduction

Plugins in Zend Framework

Table of Contents
  • Introduction
  • Using Plugins
  • Conclusion
Conclusion
Learning Zend Framework
Zend Framework手册 中文版
Introduction
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Zend Framework Quick Start
  • Autoloading in Zend Framework
  • Plugins in Zend Framework
  • Getting Started with Zend_Layout
  • Getting Started Zend_View Placeholders
  • Understanding and Using Zend Form Decorators
  • Getting Started with Zend_Session, Zend_Auth, and Zend_Acl
  • Getting Started with Zend_Search_Lucene
  • Getting Started with Zend_Paginator


Introduction - Zend Framework Manual

Plugins in Zend Framework
Plugins in Zend Framework
Zend Framework手册 中文版
Using Plugins

Introduction

Zend Framework makes heavy use of plugin architectures. Plugins allow for easy extensibility and customization of the framework while keeping your code separate from Zend Framework's code.

Typically, plugins in Zend Framework work as follows:

  • Plugins are classes. The actual class definition will vary based on the component -- you may need to extend an abstract class or implement an interface, but the fact remains that the plugin is itself a class.

  • Related plugins will share a common class prefix. For instance, if you have created a number of view helpers, they might all share the class prefix "Foo_View_Helper_".

  • Everything after the common prefix will be considered the plugin name or short name (versus the "long name", which is the full classname). For example, if the plugin prefix is "Foo_View_Helper_", and the class name is "Foo_View_Helper_Bar", the plugin name will be simply "Bar".

  • Plugin names are typically case sensitive. The one caveat is that the initial letter can often be either lower or uppercase; in our previous example, both "bar" and "Bar" would refer to the same plugin.

Now let's turn to using plugins.

Plugins in Zend Framework
Plugins in Zend Framework
Zend Framework手册 中文版
Using Plugins
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Plugins in Zend Framework
  • Introduction
  • Using Plugins
  • Conclusion


Using Plugins - Zend Framework Manual

Introduction
Plugins in Zend Framework
Zend Framework手册 中文版
Conclusion

Using Plugins

Components that make use of plugins typically use Zend_Loader_PluginLoader to do their work. This class has you register plugins by specifying one or more "prefix paths". The component will then call the PluginLoader's load() method, passing the plugin's short name to it. The PluginLoader will then query each prefix path to see if a class matching that short name exists. Prefix paths are searched in LIFO (last in, first out) order, so it will match those prefix paths registered last first -- allowing you to override existing plugins.

Some examples will make all of this more clear.

Example #1 Basic Plugin Example: Adding a single prefix path

In this example, we will assume some validators have been written and placed in the directory foo/plugins/validators/, and that all these classes share the class prefix "Foo_Validate_"; these two bits of information form our "prefix path". Furthermore, let's assume we have two validators, one named "Even" (ensuring a number to be validated is even), and another named "Dozens" (ensuring the number is a multiple of 12). The tree might look like this:

  1. foo/
  2. |-- plugins/
  3. |   |-- validators/
  4. |   |   |-- Even.php
  5. |   |   |-- Dozens.php

Now, we'll inform a Zend_Form_Element instance of this prefix path. Zend_Form_Element's addPrefixPath() method expects a third argument that indicates the type of plugin for which the path is being registered; in this case, it's a "validate" plugin.

  1. $element->addPrefixPath('Foo_Validate', 'foo/plugins/validators/', 'validate');

Now we can simply tell the element the short name of the validators we want to use. In the following example, we're using a mix of standard validators ("NotEmpty", "Int") and custom validators ("Even", "Dozens"):

  1. $element->addValidator('NotEmpty')
  2.         ->addValidator('Int')
  3.         ->addValidator('Even')
  4.         ->addValidator('Dozens');

When the element needs to validate, it will then request the plugin class from the PluginLoader. The first two validators will resolve to Zend_Validate_NotEmpty and Zend_Validate_Int, respectively; the next two will resolve to Foo_Validate_Even and Foo_Validate_Dozens, respectively.

Note: What happens if a plugin is not found?
 What happens if a plugin is requested, but the PluginLoader is unable to find a class matching it? For instance, in the above example, if we registered the plugin "Bar" with the element, what would happen?
The plugin loader will look through each prefix path, checking to see if a file matching the plugin name is found on that path. If the file is not found, it then moves on to the next prefix path.
Once the stack of prefix paths has been exhausted, if no matching file has been found, it will throw a Zend_Loader_PluginLoader_Exception.

Example #2 Intermediate Plugin Usage: Overriding existing plugins

One strength of the PluginLoader is that its use of a LIFO stack allows you to override existing plugins by creating your own versions locally with a different prefix path, and registering that prefix path later in the stack.

For example, let's consider Zend_View_Helper_FormButton (view helpers are one form of plugin). This view helper accepts three arguments, an element name (also used as the element's DOM identifier), a value (used as the button label), and an optional array of attributes. The helper then generates HTML markup for a form input element.

Let's say you want the helper to instead generate a true HTML button element; don't want the helper to generate a DOM identifier, but instead use the value for a CSS class selector; and that you have no interest in handling arbitrary attributes. You could accomplish this in a couple of ways. In both cases, you'd create your own view helper class that implements the behavior you want; the difference is in how you would name and invoke them.

Our first example will be to name the element with a unique name: Foo_View_Helper_CssButton, which implies the plugin name "CssButton". While this certainly is a viable approach, it poses several issues: if you've already used the Button view helper in your code, you now have to refactor; alternately, if another developer starts writing code for your application, they may inadvertently use the Button view helper instead of your new view helper.

So, the better example is to use the plugin name "Button", giving us the class name Foo_View_Helper_Button. We then register the prefix path with the view:

  1. // Zend_View::addHelperPath() utilizes the PluginLoader; however, it inverts
  2. // the arguments, as it provides a default value of "Zend_View_Helper" for the
  3. // plugin prefix.
  4. //
  5. // The below assumes your class is in the directory 'foo/view/helpers/'.
  6. $view->addHelperPath('foo/view/helpers', 'Foo_View_Helper');

Once done, anywhere you now use the "Button" helper will delegate to your custom Foo_View_Helper_Button class!

Introduction
Plugins in Zend Framework
Zend Framework手册 中文版
Conclusion
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Plugins in Zend Framework
  • Introduction
  • Using Plugins
  • Conclusion


Conclusion - Zend Framework Manual

Using Plugins
Plugins in Zend Framework
Zend Framework手册 中文版
Getting Started with Zend_Layout

Conclusion

Understanding the concept of prefix paths and overriding existing plugins will help you with your understanding of many components within the framework. Plugins are used in a variety of places:

  • Zend_Application: resources.

  • Zend_Controller_Action: action helpers.

  • Zend_Feed_Reader: plugins.

  • Zend_Form: elements, filters, validators, and decorators.

  • Zend_View: view helpers.

And several more places, besides. Learn the concepts early so you can leverage this important extension point in Zend Framework.

Note: Caveat
 We'll note here that Zend_Controller_Front has a plugin system - but it does not adhere to any of the guidelines offerred in this tutorial. The plugins registered with the front controller must be instantiated directly and registered individually with it. The reason for this is that this system predates any other plugin system in the framework, and changes to it must be carefully weighed to ensure existing plugins written by developers continue to work with it.

Using Plugins
Plugins in Zend Framework
Zend Framework手册 中文版
Getting Started with Zend_Layout
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Plugins in Zend Framework
  • Introduction
  • Using Plugins
  • Conclusion


Getting Started with Zend_Layout - Zend Framework Manual

Conclusion
Learning Zend Framework
Zend Framework手册 中文版
Introduction

Getting Started with Zend_Layout

Table of Contents
  • Introduction
  • Using Zend_Layout
  • Zend_Layout: Conclusions
Conclusion
Learning Zend Framework
Zend Framework手册 中文版
Introduction
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Zend Framework Quick Start
  • Autoloading in Zend Framework
  • Plugins in Zend Framework
  • Getting Started with Zend_Layout
  • Getting Started Zend_View Placeholders
  • Understanding and Using Zend Form Decorators
  • Getting Started with Zend_Session, Zend_Auth, and Zend_Acl
  • Getting Started with Zend_Search_Lucene
  • Getting Started with Zend_Paginator


Introduction - Zend Framework Manual

Getting Started with Zend_Layout
Getting Started with Zend_Layout
Zend Framework手册 中文版
Using Zend_Layout

Introduction

When building a website using Zend Framework MVC layers, your view scripts will typically be just snippets of HTML pertinent to the requested action. For instance, if you had the action "/user/list", you might create a view script that iterates through the users and presents an unordered list:

  1. <h2>Users</h2>
  2. <ul>
  3.     <?php if (!count($this->users)): ?>
  4.     <li>No users found</li>
  5.     <?php else: ?>
  6.     <?php foreach ($this->users as $user): ?>
  7.     <li>
  8.         <?php echo $this->escape($user->fullname) ?>
  9.         (<?php echo $this->escape($user->email) ?>)
  10.     </li>
  11.     <?php endforeach ?>
  12.     <?php endif ?>
  13. </ul>

Since this is just a snippet of HTML, it's not a valid page; it's missing a DOCTYPE declaration, and the opening HTML and BODY tags. So, the question is, where will these be created?

In early versions of Zend Framework, developers often created "header" and "footer" view scripts that had these artifacts, and then in each view script they would render them. While this methodology worked, it also made it difficult to refactor later, or to build composite content by calling multiple actions.

The » Two Step View design pattern answers many of the issues presented. In this pattern, the "application" view is created first, and then injected into the "page" view, which is then presented to the client. The page view can be thought of as your site-wide template or layout, and would have common elements used across various pages.

Within Zend Framework, Zend_Layout implements the Two Step View pattern.

Getting Started with Zend_Layout
Getting Started with Zend_Layout
Zend Framework手册 中文版
Using Zend_Layout
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Getting Started with Zend_Layout
  • Introduction
  • Using Zend_Layout
  • Zend_Layout: Conclusions


Using Zend_Layout - Zend Framework Manual

Introduction
Getting Started with Zend_Layout
Zend Framework手册 中文版
Zend_Layout: Conclusions

Using Zend_Layout

Basic usage of Zend_Layout is fairly trivial. Assuming you're using Zend_Application already, you can simply provide some configuration options and create a layout view script.

Layout Configuration

The recommended location of layouts is in a "layouts/scripts/" subdirectory of your application:

  1. application
  2. |-- Bootstrap.php
  3. |-- configs
  4. |   `-- application.ini
  5. |-- controllers
  6. |-- layouts
  7. |   `-- scripts
  8. |       |-- layout.phtml

To initialize Zend_Layout, add the following to your configuration file ("application/configs/application.ini"):

  1. resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts"
  2. resources.layout.layout = "layout"

The first line indicates where to look for layout scripts; the second line gives the name of the layout to use, minus the view script extension (which is assumed to be ".phtml" by default).

Create a Layout Script

Now that you have your configuration in place, you need to create your layout script. First, make sure that you've created the "application/layouts/scripts" directory; then, open an editor, and create the markup for your layout. Layout scripts are simply view scripts, with some slight differences.

  1. <html>
  2. <head>
  3.     <title>My Site</title>
  4. </head>
  5. <body>
  6.     <?php echo $this->layout()->content ?>
  7. </body>
  8. </html>

In the example above, you'll note the call to a layout() view helper. When you register the Zend_Layout resource, you also gain access to both an action and view helper that allow you access to the Zend_Layout instance; you can then call operations on the layout object. In this case, we're retrieving a named variable, $content, and echoing it. By default, the $content variable is populated for you from the application view script rendered. Otherwise, anything you'd normally do in a view script is perfectly valid -- call any helpers or view methods you desire.

At this point, you have a working layout script, and your application is informed of its location and knows to render it.

Accessing the Layout Object

On occasion, you may need direct access to the layout object. There are three ways you can do this:

  • Within view scripts: use the layout() view helper, which returns the Zend_Layout instance registered with the front controller plugin.

    1. <?php $layout = $this->layout(); ?>

    Since it returns the layout instance, you can also simply call methods on it, rather than assigning it to a variable.

  • Within action controllers: use the layout() action helper, which acts just like the view helper.

    1. // Calling helper as a method of the helper broker:
    2. $layout = $this->_helper->layout();
    3.
    4. // Or, more verbosely:
    5. $helper = $this->_helper->getHelper('Layout');
    6. $layout = $helper->getLayoutInstance();

    As with the view helper, since the action helper returns the layout instance, you can also simply call methods on it, rather than assigning it to a variable.

  • Elsewhere: use the static method getMvcInstance(). This will return the layout instance registered by the bootstrap resource.

    1. $layout = Zend_Layout::getMvcInstance();

  • Via the bootstrap: retrieve the layout resource, which will be the Zend_Layout instance.

    1. $layout = $bootstrap->getResource('Layout');

    Anywhere you have access to the bootstrap object, this method is preferred over using the static getMvcInstance() method.

Other Operations

In most cases, the above configuration and layout script (with modifications) will get you what you need. However, some other functionality exists you will likely use sooner or later. In all of the following examples, you may use one of the methods listed above for retrieving the layout object.

  • Setting layout variables. Zend_Layout keeps its own registry of layout-specific view variables that you can access; the $content key noted in the initial layout script sample is one such example. You can assign and retrieve these using normal property access, or via the assign() method.

    1. // Setting content:
    2. $layout->somekey = "foo"
    3.
    4. // Echoing that same content:
    5. echo $layout->somekey; // 'foo'
    6.
    7. // Using the assign() method:
    8. $layout->assign('someotherkey', 'bar');
    9.
    10. // Access to assign()'d variables remains the same:
    11. echo $layout->someotherkey; // 'bar'

  • disableLayout(). Occasionally, you may want to disable layouts; for example, when answering an Ajax request, or providing a RESTful representation of a resource. In these cases, you can call the disableLayout() method on your layout object.

    1. $layout->disableLayout();

    The opposite of this method is, of course, enableLayout(), which can be called at any time to re-enable layouts for the requested action.

  • Selecting an alternate layout: If you have multiple layouts for your site or application, you can select the layout to use at any time by simply calling the setLayout() method. Call it by specifying the name of the layout script without the file suffix.

    1. // Use the layout script "alternate.phtml":
    2. $layout->setLayout('alternate');

    The layout script should reside in the $layoutPath directory specified in your configuration. Zend_Layout will then use this new layout when rendering.

Introduction
Getting Started with Zend_Layout
Zend Framework手册 中文版
Zend_Layout: Conclusions
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Getting Started with Zend_Layout
  • Introduction
  • Using Zend_Layout
  • Zend_Layout: Conclusions


Zend_Layout: Conclusions - Zend Framework Manual

Using Zend_Layout
Getting Started with Zend_Layout
Zend Framework手册 中文版
Getting Started Zend_View Placeholders

Zend_Layout: Conclusions

Zend_Layout is a very simple wrapper around Zend_View which provides you immediately with the benefits of a Two Step View, giving you the flexibility to create a site-wide design into which you may inject your application content.

If you're looking closely at the examples, however, you may come away with the idea that the functionality is relatively limited: how do you alter the page title, inject an optional script tag, or even create an optional sidebar? These questions are addressed with the concept of a "Composite View" -- and are the subject of the next chapter in the tutorial, which covers view "placeholders."

Using Zend_Layout
Getting Started with Zend_Layout
Zend Framework手册 中文版
Getting Started Zend_View Placeholders
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Getting Started with Zend_Layout
  • Introduction
  • Using Zend_Layout
  • Zend_Layout: Conclusions


Understanding and Using Zend Form Decorators - Zend Framework Manual

View Placeholders: Conclusion
Learning Zend Framework
Zend Framework手册 中文版
Introduction

Understanding and Using Zend Form Decorators

Table of Contents
  • Introduction
  • Decorator Basics
  • Layering Decorators
  • Rendering Individual Decorators
  • Creating and Rendering Composite Elements
  • Conclusion
View Placeholders: Conclusion
Learning Zend Framework
Zend Framework手册 中文版
Introduction
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Zend Framework Quick Start
  • Autoloading in Zend Framework
  • Plugins in Zend Framework
  • Getting Started with Zend_Layout
  • Getting Started Zend_View Placeholders
  • Understanding and Using Zend Form Decorators
  • Getting Started with Zend_Session, Zend_Auth, and Zend_Acl
  • Getting Started with Zend_Search_Lucene
  • Getting Started with Zend_Paginator


Introduction - Zend Framework Manual

Understanding and Using Zend Form Decorators
Understanding and Using Zend Form Decorators
Zend Framework手册 中文版
Decorator Basics

Introduction

Zend_Form utilizes the decorator pattern in order to render elements and forms. Unlike the classic » decorator pattern, in which you pass an object to a wrapping class, decorators in Zend_Form implement a » strategy pattern, and utilize the metadata contained in an element or form in order to create a representation of it

Don't let the terminology scare you away, however; at heart, decorators in Zend_Form are not terribly difficult, and the mini-tutorials that follow should help you along the way. They will guide you through the basics of decoration, all the way to creating decorators for composite elements.

Understanding and Using Zend Form Decorators
Understanding and Using Zend Form Decorators
Zend Framework手册 中文版
Decorator Basics
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Understanding and Using Zend Form Decorators
  • Introduction
  • Decorator Basics
  • Layering Decorators
  • Rendering Individual Decorators
  • Creating and Rendering Composite Elements
  • Conclusion


Decorator Basics - Zend Framework Manual

Introduction
Understanding and Using Zend Form Decorators
Zend Framework手册 中文版
Layering Decorators

Decorator Basics

Overview of the Decorator Pattern

To begin, we'll cover some background on the » Decorator design pattern. One common technique is to define a common interface that both your originating object and decorator will implement; your decorator than accepts the originating object as a dependency, and will either proxy to it or override its methods. Let's put that into code to make it more easily understood:

  1. interface Window
  2. {
  3.     public function isOpen();
  4.     public function open();
  5.     public function close();
  6. }
  7.
  8. class StandardWindow implements Window
  9. {
  10.     protected $_open = false;
  11.
  12.     public function isOpen()
  13.     {
  14.         return $this->_open;
  15.     }
  16.
  17.     public function open()
  18.     {
  19.         if (!$this->_open) {
  20.             $this->_open = true;
  21.         }
  22.     }
  23.
  24.     public function close()
  25.     {
  26.         if ($this->_open) {
  27.             $this->_open = false;
  28.         }
  29.     }
  30. }
  31.
  32. class LockedWindow implements Window
  33. {
  34.     protected $_window;
  35.
  36.     public function __construct(Window $window)
  37.     {
  38.         $this->_window = $window;
  39.         $this->_window->close();
  40.     }
  41.
  42.     public function isOpen()
  43.     {
  44.         return false;
  45.     }
  46.
  47.     public function open()
  48.     {
  49.         throw new Exception('Cannot open locked windows');
  50.     }
  51.
  52.     public function close()
  53.     {
  54.         $this->_window->close();
  55.     }
  56. }

You then create an object of type StandardWindow, pass it to the constructor of LockedWindow, and your window instance now has different behavior. The beauty is that you don't have to implement any sort of "locking" functionality on your standard window class -- the decorator takes care of that for you. In the meantime, you can pass your locked window around as if it were just another window.

One particular place where the decorator pattern is useful is for creating textual representations of objects. As an example, you might have a "Person" object that, by itself, has no textual representation. By using the Decorator pattern, you can create an object that will act as if it were a Person, but also provide the ability to render that Person textually.

In this particular example, we're going to use » duck typing instead of an explicit interface. This allows our implementation to be a bit more flexible, while still allowing the decorator object to act exactly as if it were a Person object.

  1. class Person
  2. {
  3.     public function setFirstName($name) {}
  4.     public function getFirstName() {}
  5.     public function setLastName($name) {}
  6.     public function getLastName() {}
  7.     public function setTitle($title) {}
  8.     public function getTitle() {}
  9. }
  10.
  11. class TextPerson
  12. {
  13.     protected $_person;
  14.
  15.     public function __construct(Person $person)
  16.     {
  17.         $this->_person = $person;
  18.     }
  19.
  20.     public function __call($method, $args)
  21.     {
  22.         if (!method_exists($this->_person, $method)) {
  23.             throw new Exception('Invalid method called on HtmlPerson: '
  24.                 .  $method);
  25.         }
  26.         return call_user_func_array(array($this->_person, $method), $args);
  27.     }
  28.
  29.     public function __toString()
  30.     {
  31.         return $this->_person->getTitle() . ' '
  32.             . $this->_person->getFirstName() . ' '
  33.             . $this->_person->getLastName();
  34.     }
  35. }

In this example, you pass your Person instance to the TextPerson constructor. By using method overloading, you are able to continue to call all the methods of Person -- to set the first name, last name, or title -- but you also now gain a string representation via the __toString() method.

This latter example is getting close to how Zend_Form decorators work. The key difference is that instead of a decorator wrapping the element, the element has one or more decorators attached to it that it then injects itself into in order to render. The decorator then can access the element's methods and properties in order to create a representation of the element -- or a subset of it.

Creating Your First Decorator

Zend_Form decorators all implement a common interface, Zend_Form_Decorator_Interface. That interface provides the ability to set decorator-specific options, register and retrieve the element, and render. A base decorator, Zend_Form_Decorator_Abstract, provides most of the functionality you will ever need, with the exception of the rendering logic.

Let's consider a situation where we simply want to render an element as a standard form text input with a label. We won't worry about error handling or whether or not the element should be wrapped within other tags for now -- just the basics. Such a decorator might look like this:

  1. class My_Decorator_SimpleInput extends Zend_Form_Decorator_Abstract
  2. {
  3.     protected $_format = '<label for="%s">%s</label>'
  4.                        . '<input id="%s" name="%s" type="text" value="%s"/>';
  5.
  6.     public function render($content)
  7.     {
  8.         $element = $this->getElement();
  9.         $name    = htmlentities($element->getFullyQualifiedName());
  10.         $label   = htmlentities($element->getLabel());
  11.         $id      = htmlentities($element->getId());
  12.         $value   = htmlentities($element->getValue());
  13.
  14.         $markup  = sprintf($this->_format, $name, $label, $id, $name, $value);
  15.         return $markup;
  16.     }
  17. }

Let's create an element that uses this decorator:

  1. $decorator = new My_Decorator_SimpleInput();
  2. $element   = new Zend_Form_Element('foo', array(
  3.     'label'      => 'Foo',
  4.     'belongsTo'  => 'bar',
  5.     'value'      => 'test',
  6.     'decorators' => array($decorator),
  7. ));

Rendering this element results in the following markup:

  1. <label for="bar[foo]">Foo</label>
  2. <input id="bar-foo" name="bar[foo]" type="text" value="test"/>

You could also put this class in your library somewhere, inform your element of that path, and refer to the decorator as simply "SimpleInput" as well:

  1. $element = new Zend_Form_Element('foo', array(
  2.     'label'      => 'Foo',
  3.     'belongsTo'  => 'bar',
  4.     'value'      => 'test',
  5.     'prefixPath' => array('decorator' => array(
  6.         'My_Decorator' => 'path/to/decorators/',
  7.     )),
  8.     'decorators' => array('SimpleInput'),
  9. ));

This gives you the benefit of re-use in other projects, and also opens the door for providing alternate implementations of that decorator later.

In the next section, we'll look at how to combine decorators in order to create composite output.

Introduction
Understanding and Using Zend Form Decorators
Zend Framework手册 中文版
Layering Decorators
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Understanding and Using Zend Form Decorators
  • Introduction
  • Decorator Basics
  • Layering Decorators
  • Rendering Individual Decorators
  • Creating and Rendering Composite Elements
  • Conclusion


Layering Decorators - Zend Framework Manual

Decorator Basics
Understanding and Using Zend Form Decorators
Zend Framework手册 中文版
Rendering Individual Decorators

Layering Decorators

If you were following closely in the previous section, you may have noticed that a decorator's render() method takes a single argument, $content. This is expected to be a string. render() will then take this string and decide to either replace it, append to it, or prepend it. This allows you to have a chain of decorators -- which allows you to create decorators that render only a subset of the element's metadata, and then layer these decorators to build the full markup for the element.

Let's look at how this works in practice.

For most form element types, the following decorators are used:

  • ViewHelper (render the form input using one of the standard form view helpers).

  • Errors (render validation errors via an unordered list).

  • Description (render any description attached to the element; often used for tooltips).

  • HtmlTag (wrap all of the above in a <dd> tag.

  • Label (render the label preceding the above, wrapped in a <dt> tag.

You'll notice that each of these decorators does just one thing, and operates on one specific piece of metadata stored in the form element: the Errors decorator pulls validation errors and renders them; the Label decorator pulls just the label and renders it. This allows the individual decorators to be very succinct, repeatable, and, more importantly, testable.

It's also where that $content argument comes into play: each decorator's render() method is designed to accept content, and then either replace it (usually by wrapping it), prepend to it, or append to it.

So, it's best to think of the process of decoration as one of building an onion from the inside out.

To simplify the process, we'll take a look at the example from the previous section. Recall:

  1. class My_Decorator_SimpleInput extends Zend_Form_Decorator_Abstract
  2. {
  3.     protected $_format = '<label for="%s">%s</label>'
  4.                        . '<input id="%s" name="%s" type="text" value="%s"/>';
  5.
  6.     public function render($content)
  7.     {
  8.         $element = $this->getElement();
  9.         $name    = htmlentities($element->getFullyQualifiedName());
  10.         $label   = htmlentities($element->getLabel());
  11.         $id      = htmlentities($element->getId());
  12.         $value   = htmlentities($element->getValue());
  13.
  14.         $markup  = sprintf($this->_format, $id, $label, $id, $name, $value);
  15.         return $markup;
  16.     }
  17. }

Let's now remove the label functionality, and build a separate decorator for that.

  1. class My_Decorator_SimpleInput extends Zend_Form_Decorator_Abstract
  2. {
  3.     protected $_format = '<input id="%s" name="%s" type="text" value="%s"/>';
  4.
  5.     public function render($content)
  6.     {
  7.         $element = $this->getElement();
  8.         $name    = htmlentities($element->getFullyQualifiedName());
  9.         $id      = htmlentities($element->getId());
  10.         $value   = htmlentities($element->getValue());
  11.
  12.         $markup  = sprintf($this->_format, $id, $name, $value);
  13.         return $markup;
  14.     }
  15. }
  16.
  17. class My_Decorator_SimpleLabel extends Zend_Form_Decorator_Abstract
  18. {
  19.     protected $_format = '<label for="%s">%s</label>';
  20.
  21.     public function render($content)
  22.     {
  23.         $element = $this->getElement();
  24.         $id      = htmlentities($element->getId());
  25.         $label   = htmlentities($element->getLabel());
  26.
  27.         $markup = sprint($this->_format, $id, $label);
  28.         return $markup;
  29.     }
  30. }

Now, this may look all well and good, but here's the problem: as written currently, the last decorator to run wins, and overwrites everything. You'll end up with just the input, or just the label, depending on which you register last.

To overcome this, simply concatenate the passed in $content with the markup somehow:

  1. return $content . $markup;

The problem with the above approach comes when you want to programmatically choose whether the original content should precede or append the new markup. Fortunately, there's a standard mechanism for this already; Zend_Form_Decorator_Abstract has a concept of placement and defines some constants for matching it. Additionally, it allows specifying a separator to place between the two. Let's make use of those:

  1. class My_Decorator_SimpleInput extends Zend_Form_Decorator_Abstract
  2. {
  3.     protected $_format = '<input id="%s" name="%s" type="text" value="%s"/>';
  4.
  5.     public function render($content)
  6.     {
  7.         $element = $this->getElement();
  8.         $name    = htmlentities($element->getFullyQualifiedName());
  9.         $id      = htmlentities($element->getId());
  10.         $value   = htmlentities($element->getValue());
  11.
  12.         $markup  = sprintf($this->_format, $id, $name, $value);
  13.
  14.         $placement = $this->getPlacement();
  15.         $separator = $this->getSeparator();
  16.         switch ($placement) {
  17.             case self::PREPEND:
  18.                 return $markup . $separator . $content;
  19.             case self::APPEND:
  20.             default:
  21.                 return $content . $separator . $markup;
  22.         }
  23.     }
  24. }
  25.
  26. class My_Decorator_SimpleLabel extends Zend_Form_Decorator_Abstract
  27. {
  28.     protected $_format = '<label for="%s">%s</label>';
  29.
  30.     public function render($content)
  31.     {
  32.         $element = $this->getElement();
  33.         $id      = htmlentities($element->getId());
  34.         $label   = htmlentities($element->getLabel());
  35.
  36.         $markup = sprint($this->_format, $id, $label);
  37.
  38.         $placement = $this->getPlacement();
  39.         $separator = $this->getSeparator();
  40.         switch ($placement) {
  41.             case self::APPEND:
  42.                 return $markup . $separator . $content;
  43.             case self::PREPEND:
  44.             default:
  45.                 return $content . $separator . $markup;
  46.         }
  47.     }
  48. }

Notice in the above that I'm switching the default case for each; the assumption will be that labels prepend content, and input appends.

Now, let's create a form element that uses these:

  1. $element = new Zend_Form_Element('foo', array(
  2.     'label'      => 'Foo',
  3.     'belongsTo'  => 'bar',
  4.     'value'      => 'test',
  5.     'prefixPath' => array('decorator' => array(
  6.         'My_Decorator' => 'path/to/decorators/',
  7.     )),
  8.     'decorators' => array(
  9.         'SimpleInput',
  10.         'SimpleLabel',
  11.     ),
  12. ));

How will this work? When we call render(), the element will iterate through the various attached decorators, calling render() on each. It will pass an empty string to the very first, and then whatever content is created will be passed to the next, and so on:

  • Initial content is an empty string: ''.

  • '' is passed to the SimpleInput decorator, which then generates a form input that it appends to the empty string: <input id="bar-foo" name="bar[foo]" type="text" value="test"/>.

  • The input is then passed as content to the SimpleLabel decorator, which generates a label and prepends it to the original content; the default separator is a PHP_EOL character, giving us this: <label for="bar-foo">\n<input id="bar-foo" name="bar[foo]" type="text" value="test"/>.

But wait a second! What if you wanted the label to come after the input for some reason? Remember that "placement" flag? You can pass it as an option to the decorator. The easiest way to do this is to pass an array of options with the decorator during element creation:

  1. $element = new Zend_Form_Element('foo', array(
  2.     'label'      => 'Foo',
  3.     'belongsTo'  => 'bar',
  4.     'value'      => 'test',
  5.     'prefixPath' => array('decorator' => array(
  6.         'My_Decorator' => 'path/to/decorators/',
  7.     )),
  8.     'decorators' => array(
  9.         'SimpleInput'
  10.         array('SimpleLabel', array('placement' => 'append')),
  11.     ),
  12. ));

Notice that when passing options, you must wrap the decorator within an array; this hints to the constructor that options are available. The decorator name is the first element of the array, and options are passed in an array to the second element of the array.

The above results in the markup <input id="bar-foo" name="bar[foo]" type="text" value="test"/>\n<label for="bar-foo">.

Using this technique, you can have decorators that target specific metadata of the element or form and create only the markup relevant to that metadata; by using mulitiple decorators, you can then build up the complete element markup. Our onion is the result.

There are pros and cons to this approach. First, the cons:

  • More complex to implement. You have to pay careful attention to the decorators you use and what placement you utilize in order to build up the markup in the correct sequence.

  • More resource intensive. More decorators means more objects; multiply this by the number of elements you have in a form, and you may end up with some serious resource usage. Caching can help here.

The advantages are compelling, though:

  • Reusable decorators. You can create truly re-usable decorators with this technique, as you don't have to worry about the complete markup, but only markup for one or a few pieces of element or form metadata.

  • Ultimate flexibility. You can theoretically generate any markup combination you want from a small number of decorators.

While the above examples are the intended usage of decorators within Zend_Form, it's often hard to wrap your head around how the decorators interact with one another to build the final markup. For this reason, some flexibility was added in the 1.7 series to make rendering individual decorators possible -- which gives some Rails-like simplicity to rendering forms. We'll look at that in the next section.

Decorator Basics
Understanding and Using Zend Form Decorators
Zend Framework手册 中文版
Rendering Individual Decorators
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Understanding and Using Zend Form Decorators
  • Introduction
  • Decorator Basics
  • Layering Decorators
  • Rendering Individual Decorators
  • Creating and Rendering Composite Elements
  • Conclusion


Rendering Individual Decorators - Zend Framework Manual

Layering Decorators
Understanding and Using Zend Form Decorators
Zend Framework手册 中文版
Creating and Rendering Composite Elements

Rendering Individual Decorators

In the previous section, we looked at how you can combine decorators to create complex output. We noted that while you have a ton of flexibility with this approach, it also adds some complexity and overhead. In this section, we will examine how to render decorators individually in order to create custom markup for forms and/or individual elements.

Once you have registered your decorators, you can later retrieve them by name from the element. Let's review the previous example:

  1. $element = new Zend_Form_Element('foo', array(
  2.     'label'      => 'Foo',
  3.     'belongsTo'  => 'bar',
  4.     'value'      => 'test',
  5.     'prefixPath' => array('decorator' => array(
  6.         'My_Decorator' => 'path/to/decorators/',
  7.     )),
  8.     'decorators' => array(
  9.         'SimpleInput'
  10.         array('SimpleLabel', array('placement' => 'append')),
  11.     ),
  12. ));

If we wanted to pull and render just the SimpleInput decorator, we can do so using the getDecorator() method:

  1. $decorator = $element->getDecorator('SimpleInput');
  2. echo $decorator->render('');

This is pretty easy, but it can be made even easier; let's do it in a single line:

  1. echo $element->getDecorator('SimpleInput')->render('');

Not too bad, but still a little complex. To make this easier, a shorthand notation was introduced into Zend_Form in 1.7: you can render any registered decorator by calling a method of the format renderDecoratorName(). This will effectively perform what you see above, but makes the $content argument optional and simplifies the usage:

  1. echo $element->renderSimpleInput();

This is a neat trick, but how and why would you use it?

Many developers and designers have very precise markup needs for their forms. They would rather have full control over the output than rely on a more automated solution which may or may not conform to their design. In other cases, the form layout may require a lot of specialized markup -- grouping arbitrary elements, making some invisible unless a particular link is selected, etc.

Let's utilize the ability to render individual decorators to create some specialized markup.

First, let's define a form. Our form will capture a user's demographic details. The markup will be highly customized, and in some cases use view helpers directly instead of form elements in order to achieve its goals. Here is the basic form definition:

  1. class My_Form_UserDemographics extends Zend_Form
  2. {
  3.     public function init()
  4.     {
  5.         // Add a path for my own decorators
  6.         $this->addElementPrefixPaths(array(
  7.             'decorator' => array('My_Decorator' => 'My/Decorator'),
  8.         ));
  9.
  10.         $this->addElement('text', 'firstName', array(
  11.             'label' => 'First name: ',
  12.         ));
  13.         $this->addElement('text', 'lastName', array(
  14.             'label' => 'Last name: ',
  15.         ));
  16.         $this->addElement('text', 'title', array(
  17.             'label' => 'Title: ',
  18.         ));
  19.         $this->addElement('text', 'dateOfBirth', array(
  20.             'label' => 'Date of Birth (DD/MM/YYYY): ',
  21.         ));
  22.         $this->addElement('text', 'email', array(
  23.             'label' => 'Your email address: ',
  24.         ));
  25.         $this->addElement('password', 'password', array(
  26.             'label' => 'Password: ',
  27.         ));
  28.         $this->addElement('password', 'passwordConfirmation', array(
  29.             'label' => 'Confirm Password: ',
  30.         ));
  31.     }
  32. }

Note: We're not defining any validators or filters at this time, as they are not relevant to the discussion of decoration. In a real-world scenario, you should define them.

With that out of the way, let's consider how we might want to display this form. One common idiom with first/last names is to display them on a single line; when a title is provided, that is often on the same line as well. Dates, when not using a JavaScript date chooser, will often be separated into three fields displayed side by side.

Let's use the ability to render an element's decorators one by one to accomplish this. First, let's note that no explicit decorators were defined for the given elements. As a refresher, the default decorators for (most) elements are:

  • ViewHelper: utilize a view helper to render a form input

  • Errors: utilize the FormErrors view helper to render validation errors

  • Description: utilize the FormNote view helper to render the element description (if any)

  • HtmlTag: wrap the above three items in a <dd> tag

  • Label: render the element label using the FormLabel view helper (and wrap it in a <dt> tag)

Also, as a refresher, you can access any element of a form as if it were a class property; simply reference the element by the name you assigned it.

Our view script might then look like this:

  1. <?php
  2. $form = $this->form;
  3. // Remove <dt> from label generation
  4. foreach ($form->getElements() as $element) {
  5.     $element->getDecorator('label')->setOption('tag', null);
  6. }
  7. ?>
  8. <form method="<?php echo $form->getMethod() ?>" action="<?php echo
  9.     $form->getAction()?>">
  10.     <div class="element">
  11.         <?php echo $form->title->renderLabel()
  12.               . $form->title->renderViewHelper() ?>
  13.         <?php echo $form->firstName->renderLabel()
  14.               . $form->firstName->renderViewHelper() ?>
  15.         <?php echo $form->lastName->renderLabel()
  16.               . $form->lastName->renderViewHelper() ?>
  17.     </div>
  18.     <div class="element">
  19.         <?php echo $form->dateOfBirth->renderLabel() ?>
  20.         <?php echo $this->formText('dateOfBirth[day]', '', array(
  21.             'size' => 2, 'maxlength' => 2)) ?>
  22.         /
  23.         <?php echo $this->formText('dateOfBirth[month]', '', array(
  24.             'size' => 2, 'maxlength' => 2)) ?>
  25.         /
  26.         <?php echo $this->formText('dateOfBirth[year]', '', array(
  27.             'size' => 4, 'maxlength' => 4)) ?>
  28.     </div>
  29.     <div class="element">
  30.         <?php echo $form->password->renderLabel()
  31.               . $form->password->renderViewHelper() ?>
  32.     </div>
  33.     <div class="element">
  34.         <?php echo $form->passwordConfirmation->renderLabel()
  35.               . $form->passwordConfirmation->renderViewHelper() ?>
  36.     </div>
  37.     <?php echo $this->formSubmit('submit', 'Save') ?>
  38. </form>

If you use the above view script, you'll get approximately the following HTML (approximate, as the HTML below is formatted):

  1. <form method="post" action="">
  2.     <div class="element">
  3.         <label for="title" tag="" class="optional">Title:</label>
  4.         <input type="text" name="title" id="title" value=""/>
  5.
  6.         <label for="firstName" tag="" class="optional">First name:</label>
  7.         <input type="text" name="firstName" id="firstName" value=""/>
  8.
  9.         <label for="lastName" tag="" class="optional">Last name:</label>
  10.         <input type="text" name="lastName" id="lastName" value=""/>
  11.     </div>
  12.
  13.     <div class="element">
  14.         <label for="dateOfBirth" tag="" class="optional">Date of Birth
  15.             (DD/MM/YYYY):</label>
  16.         <input type="text" name="dateOfBirth[day]" id="dateOfBirth-day"
  17.             value="" size="2" maxlength="2"/>
  18.         /
  19.         <input type="text" name="dateOfBirth[month]" id="dateOfBirth-month"
  20.             value="" size="2" maxlength="2"/>
  21.         /
  22.         <input type="text" name="dateOfBirth[year]" id="dateOfBirth-year"
  23.             value="" size="4" maxlength="4"/>
  24.     </div>
  25.
  26.     <div class="element">
  27.         <label for="password" tag="" class="optional">Password:</label>
  28.         <input type="password" name="password" id="password" value=""/>
  29.     </div>
  30.
  31.     <div class="element">
  32.         <label for="passwordConfirmation" tag="" class="" id="submit"
  33.             value="Save"/>
  34. </form>

It may not be truly pretty, but with some CSS, it could be made to look exactly how you might want to see it. The main point, however, is that this form was generated using almost entirely custom markup, while still leveraging decorators for the most common markup (and to ensure things like escaping with htmlentities and value injection occur).

By this point in the tutorial, you should be getting fairly comfortable with the markup possibilities using Zend_Form's decorators. In the next section, we'll revisit the date element from above, and demonstrate how to create a custom element and decorator for composite elements.

Layering Decorators
Understanding and Using Zend Form Decorators
Zend Framework手册 中文版
Creating and Rendering Composite Elements
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Understanding and Using Zend Form Decorators
  • Introduction
  • Decorator Basics
  • Layering Decorators
  • Rendering Individual Decorators
  • Creating and Rendering Composite Elements
  • Conclusion


Creating and Rendering Composite Elements - Zend Framework Manual

Rendering Individual Decorators
Understanding and Using Zend Form Decorators
Zend Framework手册 中文版
Conclusion

Creating and Rendering Composite Elements

In the last section, we had an example showing a "date of birth element":

  1. <div class="element">
  2.     <?php echo $form->dateOfBirth->renderLabel() ?>
  3.     <?php echo $this->formText('dateOfBirth[day]', '', array(
  4.         'size' => 2, 'maxlength' => 2)) ?>
  5.     /
  6.     <?php echo $this->formText('dateOfBirth[month]', '', array(
  7.         'size' => 2, 'maxlength' => 2)) ?>
  8.     /
  9.     <?php echo $this->formText('dateOfBirth[year]', '', array(
  10.         'size' => 4, 'maxlength' => 4)) ?>
  11. </div>

How might you represent this element as a Zend_Form_Element? How might you write a decorator to render it?

The Element

The questions about how the element would work include:

  • How would you set and retrieve the value?

  • How would you validate the value?

  • Regardless, how would you then allow for discrete form inputs for the three segments (day, month, year)?

The first two questions center around the form element itself: how would setValue() and getValue() work? There's actually another question implied by the question about the decorator: how would you retrieve the discrete date segments from the element and/or set them?

The solution is to override the setValue() method of your element to provide some custom logic. In this particular case, our element should have three discrete behaviors:

  • If an integer timestamp is provided, it should be used to determine and store the day, month, and year.

  • If a textual string is provided, it should be cast to a timestamp, and then that value used to determine and store the day, month, and year.

  • If an array containing keys for date, month, and year is provided, those values should be stored.

Internally, the day, month, and year will be stored discretely. When the value of the element is retrieved, it will be done so in a normalized string format. We'll override getValue() as well to assemble the discrete date segments into a final string.

Here's what the class would look like:

  1. class My_Form_Element_Date extends Zend_Form_Element_Xhtml
  2. {
  3.     protected $_dateFormat = '%year%-%month%-%day%';
  4.     protected $_day;
  5.     protected $_month;
  6.     protected $_year;
  7.
  8.     public function setDay($value)
  9.     {
  10.         $this->_day = (int) $value;
  11.         return $this;
  12.     }
  13.
  14.     public function getDay()
  15.     {
  16.         return $this->_day;
  17.     }
  18.
  19.     public function setMonth($value)
  20.     {
  21.         $this->_month = (int) $value;
  22.         return $this;
  23.     }
  24.
  25.     public function getMonth()
  26.     {
  27.         return $this->_month;
  28.     }
  29.
  30.     public function setYear($value)
  31.     {
  32.         $this->_year = (int) $value;
  33.         return $this;
  34.     }
  35.
  36.     public function getYear()
  37.     {
  38.         return $this->_year;
  39.     }
  40.
  41.     public function setValue($value)
  42.     {
  43.         if (is_int($value)) {
  44.             $this->setDay(date('d', $value))
  45.                  ->setMonth(date('m', $value))
  46.                  ->setYear(date('Y', $value));
  47.         } elseif (is_string($value)) {
  48.             $date = strtotime($value);
  49.             $this->setDay(date('d', $date))
  50.                  ->setMonth(date('m', $date))
  51.                  ->setYear(date('Y', $date));
  52.         } elseif (is_array($value)
  53.                   && (isset($value['day'])
  54.                       && isset($value['month'])
  55.                       && isset($value['year'])
  56.                   )
  57.         ) {
  58.             $this->setDay($value['day'])
  59.                  ->setMonth($value['month'])
  60.                  ->setYear($value['year']);
  61.         } else {
  62.             throw new Exception('Invalid date value provided');
  63.         }
  64.
  65.         return $this;
  66.     }
  67.
  68.     public function getValue()
  69.     {
  70.         return str_replace(
  71.             array('%year%', '%month%', '%day%'),
  72.             array($this->getYear(), $this->getMonth(), $this->getDay()),
  73.             $this->_dateFormat
  74.         );
  75.     }
  76. }

This class gives some nice flexibility -- we can set default values from our database, and be certain that the value will be stored and represented correctly. Additionally, we can allow for the value to be set from an array passed via form input. Finally, we have discrete accessors for each date segment, which we can now use in a decorator to create a composite element.

The Decorator

Revisiting the example from the last section, let's assume that we want users to input each of the year, month, and day separately. PHP fortunately allows us to use array notation when creating elements, so it's still possible to capture these three entities into a single value -- and we've now created a Zend_Form element that can handle such an array value.

The decorator is relatively simple: it will grab the day, month, and year from the element, and pass each to a discrete view helper to render individual form inputs; these will then be aggregated to form the final markup.

  1. class My_Form_Decorator_Date extends Zend_Form_Decorator_Abstract
  2. {
  3.     public function render($content)
  4.     {
  5.         $element = $this->getElement();
  6.         if (!$element instanceof My_Form_Element_Date) {
  7.             // only want to render Date elements
  8.             return $content;
  9.         }
  10.
  11.         $view = $element->getView();
  12.         if (!$view instanceof Zend_View_Interface) {
  13.             // using view helpers, so do nothing if no view present
  14.             return $content;
  15.         }
  16.
  17.         $day   = $element->getDay();
  18.         $month = $element->getMonth();
  19.         $year  = $element->getYear();
  20.         $name  = $element->getFullyQualifiedName();
  21.
  22.         $params = array(
  23.             'size'      => 2,
  24.             'maxlength' => 2,
  25.         );
  26.         $yearParams = array(
  27.             'size'      => 4,
  28.             'maxlength' => 4,
  29.         );
  30.
  31.         $markup = $view->formText($name . '[day]', $day, $params)
  32.                 . ' / ' . $view->formText($name . '[month]', $month, $params)
  33.                 . ' / ' . $view->formText($name . '[year]', $year, $yearParams);
  34.
  35.         switch ($this->getPlacement()) {
  36.             case self::PREPEND:
  37.                 return $markup . $this->getSeparator() . $content;
  38.             case self::APPEND:
  39.             default:
  40.                 return $content . $this->getSeparator() . $markup;
  41.         }
  42.     }
  43. }

We now have to do a minor tweak to our form element, and tell it that we want to use the above decorator as a default. That takes two steps. First, we need to inform the element of the decorator path. We can do that in the constructor:

  1. class My_Form_Element_Date extends Zend_Form_Element_Xhtml
  2. {
  3.     // ...
  4.
  5.     public function __construct($spec, $options = null)
  6.     {
  7.         $this->addPrefixPath(
  8.             'My_Form_Decorator',
  9.             'My/Form/Decorator',
  10.             'decorator'
  11.         );
  12.         parent::__construct($spec, $options);
  13.     }
  14.
  15.     // ...
  16. }

Note that this is being done in the constructor and not in init(). This is for two reasons. First, it allows extending the element later to add logic in init without needing to worry about calling parent::init(). Second, it allows passing additional plugin paths via configuration or within an init method that will then allow overriding the default Date decorator with my own replacement.

Next, we need to override the loadDefaultDecorators() method to use our new Date decorator:

  1. class My_Form_Element_Date extends Zend_Form_Element_Xhtml
  2. {
  3.     // ...
  4.
  5.     public function loadDefaultDecorators()
  6.     {
  7.         if ($this->loadDefaultDecoratorsIsDisabled()) {
  8.             return;
  9.         }
  10.
  11.         $decorators = $this->getDecorators();
  12.         if (empty($decorators)) {
  13.             $this->addDecorator('Date')
  14.                  ->addDecorator('Errors')
  15.                  ->addDecorator('Description', array(
  16.                      'tag'   => 'p',
  17.                      'class' => 'description'
  18.                  ))
  19.                  ->addDecorator('HtmlTag', array(
  20.                      'tag' => 'dd',
  21.                      'id'  => $this->getName() . '-element'
  22.                  ))
  23.                  ->addDecorator('Label', array('tag' => 'dt'));
  24.         }
  25.     }
  26.
  27.     // ...
  28. }

What does the final output look like? Let's consider the following element:

  1. $d = new My_Form_Element_Date('dateOfBirth');
  2. $d->setLabel('Date of Birth: ')
  3.   ->setView(new Zend_View());
  4.
  5. // These are equivalent:
  6. $d->setValue('20 April 2009');
  7. $d->setValue(array('year' => '2009', 'month' => '04', 'day' => '20'));

If you then echo this element, you get the following markup (with some slight whitespace modifications for readability):

  1. <dt id="dateOfBirth-label"><label for="dateOfBirth" class="optional">
  2.     Date of Birth:
  3. </label></dt>
  4. <dd id="dateOfBirth-element">
  5.     <input type="text" name="dateOfBirth[day]" id="dateOfBirth-day"
  6.         value="20" size="2" maxlength="2"> /
  7.     <input type="text" name="dateOfBirth[month]" id="dateOfBirth-month"
  8.         value="4" size="2" maxlength="2"> /
  9.     <input type="text" name="dateOfBirth[year]" id="dateOfBirth-year"
  10.         value="2009" size="4" maxlength="4">
  11. </dd>

Conclusion

We now have an element that can render multiple related form input fields, and then handle the aggregated fields as a single entity -- the dateOfBirth element will be passed as an array to the element, and the element will then, as we noted earlier, create the appropriate date segments and return a value we can use for most backends.

Additionally, we can use different decorators with the element. If we wanted to use a » Dojo DateTextBox dijit decorator -- which accepts and returns string values -- we can, with no modifications to the element itself.

In the end, you get a uniform element API you can use to describe an element representing a composite value.

Rendering Individual Decorators
Understanding and Using Zend Form Decorators
Zend Framework手册 中文版
Conclusion
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Understanding and Using Zend Form Decorators
  • Introduction
  • Decorator Basics
  • Layering Decorators
  • Rendering Individual Decorators
  • Creating and Rendering Composite Elements
  • Conclusion


Conclusion - Zend Framework Manual

Creating and Rendering Composite Elements
Understanding and Using Zend Form Decorators
Zend Framework手册 中文版
Getting Started with Zend_Session, Zend_Auth, and Zend_Acl

Conclusion

Form decorators are a system that takes some time to learn. At first, they will likely feel cumbersome and overly complex. Hopefully the various topics covered in this chapter will help you to understand both how they work, as well as strategies for using them effectively in your forms.

Creating and Rendering Composite Elements
Understanding and Using Zend Form Decorators
Zend Framework手册 中文版
Getting Started with Zend_Session, Zend_Auth, and Zend_Acl
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Understanding and Using Zend Form Decorators
  • Introduction
  • Decorator Basics
  • Layering Decorators
  • Rendering Individual Decorators
  • Creating and Rendering Composite Elements
  • Conclusion


Getting Started with Zend_Search_Lucene - Zend Framework Manual

Building an Authorization System in Zend Framework
Learning Zend Framework
Zend Framework手册 中文版
Zend_Search_Lucene Introduction

Getting Started with Zend_Search_Lucene

Table of Contents
  • Zend_Search_Lucene Introduction
  • Lucene Index Structure
  • Index Opening and Creation
  • Indexing
  • Searching
  • Supported queries
  • Search result pagination
Building an Authorization System in Zend Framework
Learning Zend Framework
Zend Framework手册 中文版
Zend_Search_Lucene Introduction
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Zend Framework Quick Start
  • Autoloading in Zend Framework
  • Plugins in Zend Framework
  • Getting Started with Zend_Layout
  • Getting Started Zend_View Placeholders
  • Understanding and Using Zend Form Decorators
  • Getting Started with Zend_Session, Zend_Auth, and Zend_Acl
  • Getting Started with Zend_Search_Lucene
  • Getting Started with Zend_Paginator


Zend_Search_Lucene Introduction - Zend Framework Manual

Getting Started with Zend_Search_Lucene
Getting Started with Zend_Search_Lucene
Zend Framework手册 中文版
Lucene Index Structure

Zend_Search_Lucene Introduction

The Zend_Search_Lucene component is intended to provide a ready-for-use full-text search solution. It doesn't require any PHP extensions[1] UTF-8 mbstring or additional software to be installed, and can be used immediately after Zend Framework installation.

Zend_Search_Lucene is a pure PHP port of the popular open source full-text search engine known as Apache Lucene. See » http://lucene.apache.org/ for the details.

Information must be indexed to be available for searching. Zend_Search_Lucene and Java Lucene use a document concept known as an "atomic indexing item."

Each document is a set of fields: <name, value> pairs where name and value are UTF-8 strings[2]. Any subset of the document fields may be marked as "indexed" to include field data in the text indexing process.

Field values may or may not be tokenized while indexing. If a field is not tokenized, then the field value is stored as one term; otherwise, the current analyzer is used for tokenization.

Several analyzers are provided within the Zend_Search_Lucene package. The default analyzer works with ASCII text (since the UTF-8 analyzer needs the mbstring extension to be turned on). It is case insensitive, and it skips numbers. Use other analyzers or create your own analyzer if you need to change this behavior.

Note: Using analyzers during indexing and searching
 Important note! Search queries are also tokenized using the "current analyzer", so the same analyzer must be set as the default during both the indexing and searching process. This will guarantee that source and searched text will be transformed into terms in the same way.

Field values are optionally stored within an index. This allows the original field data to be retrieved from the index while searching. This is the only way to associate search results with the original data (internal document IDs may be changed after index optimization or auto-optimization).

The thing that should be remembered is that a Lucene index is not a database. It doesn't provide index backup mechanisms except backup of the file system directory. It doesn't provide transactional mechanisms though concurrent index update as well as concurrent update and read are supported. It doesn't compare with databases in data retrieving speed.

So it's good idea:

  • Not to use Lucene index as a storage since it may dramatically decrease search hit retrieving performance. Store only unique document identifiers (doc paths, URLs, database unique IDs) and associated data within an index. E.g. title, annotation, category, language info, avatar. (Note: a field may be included in indexing, but not stored, or stored, but not indexed).

  • To write functionality that can rebuild an index completely if it's corrupted for any reason.

Individual documents in the index may have completely different sets of fields. The same fields in different documents don't need to have the same attributes. E.g. a field may be indexed for one document and skipped from indexing for another. The same applies for storing, tokenizing, or treating field value as a binary string.

[1] Though some processing functionality requires the extension to be turned on
[2] Binary strings are also allowed to be used as field values
Getting Started with Zend_Search_Lucene
Getting Started with Zend_Search_Lucene
Zend Framework手册 中文版
Lucene Index Structure
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Getting Started with Zend_Search_Lucene
  • Zend_Search_Lucene Introduction
  • Lucene Index Structure
  • Index Opening and Creation
  • Indexing
  • Searching
  • Supported queries
  • Search result pagination


Lucene Index Structure - Zend Framework Manual

Zend_Search_Lucene Introduction
Getting Started with Zend_Search_Lucene
Zend Framework手册 中文版
Index Opening and Creation

Lucene Index Structure

In order to fully utilize Zend_Search_Lucene's capabilities with maximum performance, you need to understand it's internal index structure.

An index is stored as a set of files within a single directory.

An index consists of any number of independent segments which store information about a subset of indexed documents. Each segment has its own terms dictionary, terms dictionary index, and document storage (stored field values) [1] Zend_Search_Lucene. All segment data is stored in _xxxxx.cfs files, where xxxxx is a segment name.

Once an index segment file is created, it can't be updated. New documents are added to new segments. Deleted documents are only marked as deleted in an optional <segmentname>.del file.

Document updating is performed as separate delete and add operations, even though it's done using an update() API call [2] Zend_Search_Lucene API. This simplifies adding new documents, and allows updating concurrently with search operations.

On the other hand, using several segments (one document per segment as a borderline case) increases search time:

  • retrieving a term from a dictionary is performed for each segment;

  • the terms dictionary index is pre-loaded for each segment (this process takes the most search time for simple queries, and it also requires additional memory).

If the terms dictionary reaches a saturation point, then search through one segment is N times faster than search through N segments in most cases.

Index optimization merges two or more segments into a single new one. A new segment is added to the index segments list, and old segments are excluded.

Segment list updates are performed as an atomic operation. This gives the ability of concurrently adding new documents, performing index optimization, and searching through the index.

Index auto-optimization is performed after each new segment generation. It merges sets of the smallest segments into larger segments, and larger segments into even larger segments, if we have enough segments to merge.

Index auto-optimization is controlled by three options:

  • MaxBufferedDocs (the minimal number of documents required before the buffered in-memory documents are written into a new segment);

  • MaxMergeDocs (the largest number of documents ever merged by an optimization operation); and

  • MergeFactor (which determines how often segment indices are merged by auto-optimization operations).

If we add one document per script execution, then MaxBufferedDocs is actually not used (only one new segment with only one document is created at the end of script execution, at which time the auto-optimization process starts).

[1] Starting with Lucene 2.3, document storage files can be shared between segments; however, doesn't use this capability
[2] This call is provided only by Java Lucene now, but it's planned to extend the with similar functionality
Zend_Search_Lucene Introduction
Getting Started with Zend_Search_Lucene
Zend Framework手册 中文版
Index Opening and Creation
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Getting Started with Zend_Search_Lucene
  • Zend_Search_Lucene Introduction
  • Lucene Index Structure
  • Index Opening and Creation
  • Indexing
  • Searching
  • Supported queries
  • Search result pagination


Index Opening and Creation - Zend Framework Manual

Lucene Index Structure
Getting Started with Zend_Search_Lucene
Zend Framework手册 中文版
Indexing

Index Opening and Creation

All index operations (e.g., creating a new index, adding a document to the index, deleting a document, searching through the index) need an index object. One can be obtained using one of the following two methods.

Example #1 Lucene Index Creation

  1. $index = Zend_Search_Lucene::create($indexPath);

Example #2 Lucene Index Opening

  1. $index = Zend_Search_Lucene::open($indexPath);
Lucene Index Structure
Getting Started with Zend_Search_Lucene
Zend Framework手册 中文版
Indexing
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Getting Started with Zend_Search_Lucene
  • Zend_Search_Lucene Introduction
  • Lucene Index Structure
  • Index Opening and Creation
  • Indexing
  • Searching
  • Supported queries
  • Search result pagination


Indexing - Zend Framework Manual

Index Opening and Creation
Getting Started with Zend_Search_Lucene
Zend Framework手册 中文版
Searching

Indexing

Indexing is performed by adding a new document to an existing or new index:

  1. $index->addDocument($doc);

There are two ways to create document object. The first is to do it manually.

Example #1 Manual Document Construction

  1. $doc = new Zend_Search_Lucene_Document();
  2. $doc->addField(Zend_Search_Lucene_Field::Text('url', $docUrl));
  3. $doc->addField(Zend_Search_Lucene_Field::Text('title', $docTitle));
  4. $doc->addField(Zend_Search_Lucene_Field::unStored('contents', $docBody));
  5. $doc->addField(Zend_Search_Lucene_Field::binary('avatar', $avatarData));

The second method is to load it from HTML or Microsoft Office 2007 files:

Example #2 Document loading

  1. $doc = Zend_Search_Lucene_Document_Html::loadHTML($htmlString);
  2. $doc = Zend_Search_Lucene_Document_Docx::loadDocxFile($path);
  3. $doc = Zend_Search_Lucene_Document_Pptx::loadPptFile($path);
  4. $doc = Zend_Search_Lucene_Document_Xlsx::loadXlsxFile($path);

If a document is loaded from one of the supported formats, it still can be extended manually with new user defined fields.

Indexing Policy

You should define indexing policy within your application architectural design.

You may need an on-demand indexing configuration (something like OLTP system). In such systems, you usually add one document per user request. As such, the MaxBufferedDocs option will not affect the system. On the other hand, MaxMergeDocs is really helpful as it allows you to limit maximum script execution time. MergeFactor should be set to a value that keeps balance between the average indexing time (it's also affected by average auto-optimization time) and search performance (index optimization level is dependent on the number of segments).

If you will be primarily performing batch index updates, your configuration should use a MaxBufferedDocs option set to the maximum value supported by the available amount of memory. MaxMergeDocs and MergeFactor have to be set to values reducing auto-optimization involvement as much as possible [1]. Full index optimization should be applied after indexing.

Example #3 Index optimization

  1. $index->optimize();

In some configurations, it's more effective to serialize index updates by organizing update requests into a queue and processing several update requests in a single script execution. This reduces index opening overhead, and allows utilizing index document buffering.

[1] An additional limit is the maximum file handlers supported by the operation system for concurrent open operations
Index Opening and Creation
Getting Started with Zend_Search_Lucene
Zend Framework手册 中文版
Searching
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Getting Started with Zend_Search_Lucene
  • Zend_Search_Lucene Introduction
  • Lucene Index Structure
  • Index Opening and Creation
  • Indexing
  • Searching
  • Supported queries
  • Search result pagination


Searching - Zend Framework Manual

Indexing
Getting Started with Zend_Search_Lucene
Zend Framework手册 中文版
Supported queries

Searching

Searching is performed by using the find() method:

Example #1 Searching through the index

  1. $hits = $index->find($query);
  2.
  3. foreach ($hits as $hit) {
  4.     printf("%d %f %s\n", $hit->id, $hit->score, $hit->title);
  5. }

This example demonstrates the usage of two special search hit properties - id and score.

id is an internal document identifier used within a Lucene index. It may be used for a variety of operations, including deleting a document from the index:

Example #2 Deleting an Indexed Document

  1. $index->delete($id);

Or retrieving the document from the index:

Example #3 Retrieving an Indexed Document

  1. $doc = $index->getDocument($id);

Note: Internal Document Identifiers
 Important note! Internal document identifiers may be changed by index optimization or the auto-optimization process, but it's never changed within a single script's execution unless the addDocument() (which may involve an auto-optimization procedure) or optimize() methods are called.

The score field is a hit score. Search results are ordered by score by default (best results returned first).

It's also possible to order result sets by specific field values. See the Zend_Search_Lucene documentation for more details about this possibility.

The example also demonstrates an ability to access stored fields (e.g., $hit->title). At the first access to any hit property other than id or score, document stored fields are loaded, and the corresponding field value is returned.

This causes an ambiguity for documents having their own id or score fields; as a result, it's not recommended to use these field names within stored documents. Nevertheless, they still can be accessed via the getDocument() method:

Example #4 Accessing the original document's "id" and "score" fields

  1. $id    = $hit->getDocument()->id;
  2. $score = $hit->getDocument()->score;
Indexing
Getting Started with Zend_Search_Lucene
Zend Framework手册 中文版
Supported queries
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Getting Started with Zend_Search_Lucene
  • Zend_Search_Lucene Introduction
  • Lucene Index Structure
  • Index Opening and Creation
  • Indexing
  • Searching
  • Supported queries
  • Search result pagination


Supported queries - Zend Framework Manual

Searching
Getting Started with Zend_Search_Lucene
Zend Framework手册 中文版
Search result pagination

Supported queries

Zend_Search_Lucene and Java Lucene support a powerful query language. It allows searching for individual terms, phrases, ranges of terms; using wildcards and fuzzy search; combining queries using boolean operators; and so on.

A detailed query language description can be found in the Zend_Search_Lucene component documentation.

What follows are examples of some common query types and strategies.

Example #1 Querying for a single word

  1. hello

Searches for the word "hello" through all document fields.

Note: Default search field
 Important note! Java Lucene searches only through the "contents" field by default, but Zend_Search_Lucene searches through all fields. This behavior can be modified using the Zend_Search_Lucene::setDefaultSearchField($fieldName) method.

Example #2 Querying for multiple words

  1. hello dolly

Searches for two words. Both words are optional; at least one of them must be present in the result.

Example #3 Requiring words in a query

  1. +hello dolly

Searches for two words; "hello" is required, "dolly" is optional.

Example #4 Prohibiting words in queried documents

  1. +hello -dolly

Searches for two words; "hello" is required, 'dolly' is prohibited. In other words, if the document matches "hello", but contains the word "dolly", it will not be returned in the set of matches.

Example #5 Querying for phrases

  1. "hello dolly"

Searches for the phrase "hello dolly"; a document only matches if that exact string is present.

Example #6 Querying against specific fields

  1. title:"The Right Way" AND text:go

Searches for the phrase "The Right Way" within the title field and the word "go" within the text field.

Example #7 Querying against specific fields as well as the entire document

  1. title:"The Right Way" AND  go

Searches for the phrase "The Right Way" within the title field and the word "go" word appearing in any field of the document.

Example #8 Querying against specific fields as well as the entire document (alternate)

  1. title:Do it right

Searches for the word "Do" within the title field and the words "it" and "right" words through all fields; any single one matching will result in a document match.

Example #9 Querying with the wildcard "?"

  1. te?t

Search for words matching the pattern "te?t", where "?" is any single character.

Example #10 Querying with the wildcard "*"

  1. test*

Search for words matching the pattern "test*", where "*" is any sequence of zero or more characters.

Example #11 Querying for an inclusive range of terms

  1. mod_date:[20020101 TO 20030101]

Search for the range of terms (inclusive).

Example #12 Querying for an exclusive range of terms

  1. title:{Aida to Carmen}

Search for the range of terms (exclusive).

Example #13 Fuzzy searches

  1. roam~

Fuzzy search for the word "roam".

Example #14 Boolean searches

  1. (framework OR library) AND php

Boolean query.

All supported queries can be constructed through Zend_Search_Lucene's query construction API. Moreover, query parsing and query constructing may be combined:

Example #15 Combining parsed and constructed queries

  1. $userQuery = Zend_Search_Lucene_Search_QueryParser::parse($queryStr);
  2.
  3. $query = new Zend_Search_Lucene_Search_Query_Boolean();
  4. $query->addSubquery($userQuery, true  /* required */);
  5. $query->addSubquery($constructedQuery, true  /* required */);
Searching
Getting Started with Zend_Search_Lucene
Zend Framework手册 中文版
Search result pagination
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Getting Started with Zend_Search_Lucene
  • Zend_Search_Lucene Introduction
  • Lucene Index Structure
  • Index Opening and Creation
  • Indexing
  • Searching
  • Supported queries
  • Search result pagination


Search result pagination - Zend Framework Manual

Supported queries
Getting Started with Zend_Search_Lucene
Zend Framework手册 中文版
Getting Started with Zend_Paginator

Search result pagination

As mentioned above, search result hit objects use lazy loading for stored document fields. When any stored field is accessed, the complete document is loaded.

Do not retrieve all documents if you actually need to work only with some portion of them. Go through the search results and store document IDs (and optionally the score) somewhere to retrive documents from the index during the next script execution.

Example #1 Search result pagination example

  1. $cacheId = md5($query);
  2.
  3. if (!$resultSet = $cache->load($cacheId)) {
  4.     $hits = $index->find($query);
  5.     $resultSet = array();
  6.     foreach ($hits as $hit) {
  7.         $resultSetEntry          = array();
  8.         $resultSetEntry['id']    = $hit->id;
  9.         $resultSetEntry['score'] = $hit->score;
  10.
  11.         $resultSet[] = $resultSetEntry;
  12.     }
  13.
  14.     $cache->save($resultSet, $cacheId);
  15. }
  16.
  17. $publishedResultSet = array();
  18. for ($resultId = $startId; $resultId < $endId; $resultId++) {
  19.     $publishedResultSet[$resultId] = array(
  20.         'id'    => $resultSet[$resultId]['id'],
  21.         'score' => $resultSet[$resultId]['score'],
  22.         'doc'   => $index->getDocument($resultSet[$resultId]['id']),
  23.     );
  24. }
Supported queries
Getting Started with Zend_Search_Lucene
Zend Framework手册 中文版
Getting Started with Zend_Paginator
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Getting Started with Zend_Search_Lucene
  • Zend_Search_Lucene Introduction
  • Lucene Index Structure
  • Index Opening and Creation
  • Indexing
  • Searching
  • Supported queries
  • Search result pagination


Getting Started with Zend_Session, Zend_Auth, and Zend_Acl - Zend Framework Manual

Conclusion
Learning Zend Framework
Zend Framework手册 中文版
Building Multi-User Applications With Zend Framework

Getting Started with Zend_Session, Zend_Auth, and Zend_Acl

Table of Contents
  • Building Multi-User Applications With Zend Framework
  • Managing User Sessions In ZF
  • Authenticating Users in Zend Framework
  • Building an Authorization System in Zend Framework
Conclusion
Learning Zend Framework
Zend Framework手册 中文版
Building Multi-User Applications With Zend Framework
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Zend Framework Quick Start
  • Autoloading in Zend Framework
  • Plugins in Zend Framework
  • Getting Started with Zend_Layout
  • Getting Started Zend_View Placeholders
  • Understanding and Using Zend Form Decorators
  • Getting Started with Zend_Session, Zend_Auth, and Zend_Acl
  • Getting Started with Zend_Search_Lucene
  • Getting Started with Zend_Paginator


Building Multi-User Applications With Zend Framework - Zend Framework Manual

Getting Started with Zend_Session, Zend_Auth, and Zend_Acl
Getting Started with Zend_Session, Zend_Auth, and Zend_Acl
Zend Framework手册 中文版
Managing User Sessions In ZF

Building Multi-User Applications With Zend Framework

Zend Framework

When the original "web" was created, it was designed to be a publishing platform for predominantly static content. As demand for content on the web grew, as did the number of consumers on the internet for web content, the demand for using the web as an application platform also grew. Since the web is inherently good at delivering a simultaneous experience to many consumers from a single location, it makes it an ideal environment for building dynamically driven, multi-user, and more commonly today, social systems.

HTTP is the protocol of the web: a stateless, typically short lived, request and response protocol. This protocol was designed this way because the original intent of the web was to serve or publish static content. It is this very design that has made the web as immensely successful as it is. It is also exactly this design that brings new concerns to developers who wish to use the web as an application platform.

These concerns and responsibilities can effectively be summed up by three questions:

  • How do you distinguish one application consumer from another?

  • How do you identify a consumer as authentic?

  • How do you control what a consumer has access to?

Note: Consumer Vs. User
 Notice we use the term "consumer" instead of person. Increasingly, web applications are becoming service driven. This means that not only are real people ("users") with real web browsers consuming and using your application, but also other web applications through machine service technologies such as REST, SOAP, and XML-RPC. In this respect, people, as well as other consuming applications, should all be treated in same with regard to the concerns outlined above.

In the following chapters, we'll take a look at these common problems relating to authentication and authorization in detail. We will discover how 3 main components: Zend_Session, Zend_Auth, and Zend_Acl; provide an out-of-the-box solution as well as the extension points each have that will cater to a more customized solution.

Getting Started with Zend_Session, Zend_Auth, and Zend_Acl
Getting Started with Zend_Session, Zend_Auth, and Zend_Acl
Zend Framework手册 中文版
Managing User Sessions In ZF
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Getting Started with Zend_Session, Zend_Auth, and Zend_Acl
  • Building Multi-User Applications With Zend Framework
  • Managing User Sessions In ZF
  • Authenticating Users in Zend Framework
  • Building an Authorization System in Zend Framework


Managing User Sessions In ZF - Zend Framework Manual

Building Multi-User Applications With Zend Framework
Getting Started with Zend_Session, Zend_Auth, and Zend_Acl
Zend Framework手册 中文版
Authenticating Users in Zend Framework

Managing User Sessions In ZF

Introduction to Sessions

The success of the web is deeply rooted in the protocol that drives the web: HTTP. HTTP over TCP is by its very nature stateless, which means that inherently the web is also stateless. While this very aspect is one of the dominating factors for why the web has become such a popular medium, it also causes an interesting problem for developers that want to use the web as an application platform.

The act of interacting with a web application is typically defined by the sum of all requests sent to a web server. Since there can be many consumers being served simultaneously, the application must decide which requests belong to which consumer. These requests are typically known as a "session".

In PHP, the session problem is solved by the session extension which utilizes some state tracking, typically cookies, and some form of local storage which is exposed via the $_SESSION superglobal. In Zend Framework, the component Zend_Session adds value to the php session extension making it easier to use and depend on inside object-oriented applications.

Basic Usage of Zend_Session

The Zend_Session component is both a session manager as well as an API for storing data into a session object for long-term persistence. The Zend_Session API is for managing the options and behavior of a session, like options, starting and stopping a session, whereas Zend_Session_Namespace is the actual object used to store data.

While its generally good practice to start a session inside a bootstrap process, this is generally not necessary as all sessions will be automatically started upon the first creation of a Zend_Session_Namespace object.

Zend_Application is capable of configuring Zend_Session for you as part of the Zend_Application_Resource system. To use this, assuming your project uses Zend_Application to bootstrap, you would add the following code to your application.ini file:

  1. resources.session.save_path = APPLICATION_PATH "/../data/session"
  2. resources.session.use_only_cookies = true
  3. resources.session.remember_me_seconds = 864000

As you can see, the options passed in are the same options that you'd expect to find in the ext/session extension in PHP. Those options setup the path to the session files where data will be stored within the project. Since ini files can additionally use constants, the above will use the APPLICATION_PATH constant and relatively point to a data session directory.

Most Zend Framework components that use sessions need nothing more to use Zend_Session. At this point, you an either use a component that consumes Zend_Session, or start storing your own data inside a session with Zend_Session_Namespace.

Zend_Session_Namespace is a simple class that proxies data via an easy to use API into the Zend_Session managed $_SESSION superglobal. The reason it is called Zend_Session_Namespace is that it effectively namespaces the data inside $_SESSION, thus allowing multiple components and objects to safely store and retrieve data. In the following code, we'll explore how to build a simple session incrementing counter, starting at 1000 and resetting itself after 1999.

  1. $mysession = Zend_Session_Namespace('mysession');
  2.
  3. if (!isset($mysession->counter)) {
  4.     $mysession->counter = 1000;
  5. } else {
  6.     $mysession->counter++;
  7. }
  8.
  9. if ($mysession->counter > 1999) {
  10.     unset($mysession->counter);
  11. }

As you can see above, the session namespace object uses the magic __get, __set, __isset, and __unset to allow you to seemlessly and fluently interact with the session. The information stored in the above example is stored at $_SESSION['mysession']['counter'].

Advanced Usage of Zend_Session

Addionally, if you wanted to use the DbTable save handler for Zend_Session, you'd add the following code to your application.ini:

  1. resources.session.saveHandler.class = "Zend_Session_SaveHandler_DbTable"
  2. resources.session.saveHandler.options.name = "session"
  3. resources.session.saveHandler.options.primary.session_id = "session_id"
  4. resources.session.saveHandler.options.primary.save_path = "save_path"
  5. resources.session.saveHandler.options.primary.name = "name"
  6. resources.session.saveHandler.options.primaryAssignment.sessionId = "sessionId"
  7. resources.session.saveHandler.options.primaryAssignment.sessionSavePath = "sessionSavePath"
  8. resources.session.saveHandler.options.primaryAssignment.sessionName = "sessionName"
  9. resources.session.saveHandler.options.modifiedColumn = "modified"
  10. resources.session.saveHandler.options.dataColumn = "session_data"
  11. resources.session.saveHandler.options.lifetimeColumn = "lifetime"
Building Multi-User Applications With Zend Framework
Getting Started with Zend_Session, Zend_Auth, and Zend_Acl
Zend Framework手册 中文版
Authenticating Users in Zend Framework
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Getting Started with Zend_Session, Zend_Auth, and Zend_Acl
  • Building Multi-User Applications With Zend Framework
  • Managing User Sessions In ZF
  • Authenticating Users in Zend Framework
  • Building an Authorization System in Zend Framework


Authenticating Users in Zend Framework - Zend Framework Manual

Managing User Sessions In ZF
Getting Started with Zend_Session, Zend_Auth, and Zend_Acl
Zend Framework手册 中文版
Building an Authorization System in Zend Framework

Authenticating Users in Zend Framework

Introduction to Authentication

Once a web application has been able to distinguish one user from another by establishing a session, web applications typically want to validate the identity of a user. The process of validating a consumer as being authentic is "authentication." Authentication is made up of two distinctive parts: an identity and a set of credentials. It takes some variation of both presented to the application for processing so that it may authenticate a user.

While the most common pattern of authentication revolves around usernames and passwords, it should be stated that this is not always the case. Identities are not limited to usernames. In fact, any public identifier can be used: an assigned number, social security number, or residence address. Likewise, credentials are not limited to passwords. Credentials can come in the form of protected private information: fingerprint, eye retinal scan, passphrase, or any other obscure personal information.

Basic Usage of Zend_Auth

In the following example, we will be using Zend_Auth to complete what is probably the most prolific form of authentication: username and password from a database table. This example assumes that you have already setup your application using Zend_Application, and that inside that application you have configured a database connection.

The job of the Zend_Auth class is twofold. First, it should be able to accept an authentication adapter to use to authenticate a user. Secondly, after a successful authentication of a user, it should persist throughout each and every request that might need to know if the current user has indeed been authenticated. To persist this data, Zend_Auth consumes Zend_Session_Namespace, but you will generally never need to interact with this session object.

Lets assume we have the following database table setup:

  1. CREATE TABLE users (
  2.     id INTEGER  NOT NULL PRIMARY KEY,
  3.     username VARCHAR(50) UNIQUE NOT NULL,
  4.     password VARCHAR(32) NULL,
  5.     password_salt VARCHAR(32) NULL,
  6.     real_name VARCHAR(150) NULL
  7. )

The above demonstrates a user table that includes a username, password, and also a password salt column. This salt column is used as part of a technique called salting that would improve the security of your database of information against brute force attacks targeting the algorithm of your password hashing. » More information on salting.

For this implementation, we must first make a simple form that we can utilized as the "login form". We will use Zend_Form to accomplish this.

  1. // located at application/forms/Auth/Login.php
  2.
  3. class Default_Form_Auth_Login extends Zend_Form
  4. {
  5.     public function init()
  6.     {
  7.         $this->setMethod('post');
  8.
  9.         $this->addElement(
  10.             'text', 'username', array(
  11.                 'label' => 'Username:',
  12.                 'required' => true,
  13.                 'filters'    => array('StringTrim'),
  14.             ));
  15.
  16.         $this->addElement('password', 'password', array(
  17.             'label' => 'Password:',
  18.             'required' => true,
  19.             ));
  20.
  21.         $this->addElement('submit', 'submit', array(
  22.             'ignore'   => true,
  23.             'label'    => 'Login',
  24.             ));
  25.
  26.     }
  27. }

With the above form, we can now go about creating our login action for our authentication controller. This controller will be called "AuthController", and will be located at application/controllers/AuthController.php. It will have a single method called " loginAction()" which will serve as the self-posting action. In other words, regardless of the url was POSTed to or GETed to, this method will handle the logic.

The following code will demonstrate how to construct the proper adapter, integrate it with the form:

  1. class AuthController extends Zend_Controller_Action
  2. {
  3.
  4.     public function loginAction()
  5.     {
  6.         $db = $this->_getParam('db');
  7.
  8.         $loginForm = new Default_Form_Auth_Login($_POST);
  9.
  10.         if ($loginForm->isValid()) {
  11.
  12.             $adapter = new Zend_Auth_Adapter_DbTable(
  13.                 $db,
  14.                 'users',
  15.                 'username',
  16.                 'password',
  17.                 'MD5(CONCAT(?, password_salt))'
  18.                 );
  19.
  20.             $adapter->setIdentity($loginForm->getValue('username'));
  21.             $adapter->setCredential($loginForm->getValue('password'));
  22.
  23.             $result = $auth->authenticate($adapter);
  24.
  25.             if ($result->isValid()) {
  26.                 $this->_helper->FlashMessenger('Successful Login');
  27.                 $this->redirect('/');
  28.                 return;
  29.             }
  30.
  31.         }
  32.
  33.         $this->view->loginForm = $loginForm;
  34.
  35.     }
  36.
  37. }

The corresponding view script is quite simple for this action. It will set the current url since this form is self processing, and it will display the form. This view script is located at application/views/scripts/auth/login.phtml:

  1. $this->form->setAction($this->url());
  2. echo $this->form;

There you have it. With these basics you can expand the general concepts to include more complex authentication scenarios. For more information on other Zend_Auth adapters, have a look in the reference guide.

Managing User Sessions In ZF
Getting Started with Zend_Session, Zend_Auth, and Zend_Acl
Zend Framework手册 中文版
Building an Authorization System in Zend Framework
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Getting Started with Zend_Session, Zend_Auth, and Zend_Acl
  • Building Multi-User Applications With Zend Framework
  • Managing User Sessions In ZF
  • Authenticating Users in Zend Framework
  • Building an Authorization System in Zend Framework


Building an Authorization System in Zend Framework - Zend Framework Manual

Authenticating Users in Zend Framework
Getting Started with Zend_Session, Zend_Auth, and Zend_Acl
Zend Framework手册 中文版
Getting Started with Zend_Search_Lucene

Building an Authorization System in Zend Framework

Introduction to Authorization

After a user has been identified as being authentic, an application can go about its business of providing some useful and desirable resources to a consumer. In many cases, applications might contain different resource types, with some resources having stricter rules regarding access. This process of determining who has access to which resources is the process of "authorization". Authorization in its simplest form is the composition of these elements:

  • the identity whom wishes to be granted access

  • the resource the identity is asking permission to consume

  • and optionally, what the identity is privileged to do with the resource

In Zend Framework, the Zend_Acl component handles the task of building a tree of roles, resources and privileges to manage and query authorization requests against.

Basic Usage of Zend_Acl

When using Zend_Acl, any models can serve as roles or resources by simply implementing the proper interface. To be used in a role capacity, the class must implement the Zend_Acl, which requires only getRoleId(). To be used in a resource capacity, a class must implement the Zend_Acl_Resource_Interface which similarly requires the class implement the getResourceId() method.

Demonstrated below is a simple user model. This model can take part in our ACL system simply by implementing the Zend_Acl_Role_Interface. The method getRoleId() will return the id "guest" when an ID is not known, or it will return the role ID that was assigned to this actual user object. This value can effectively come from anywhere, a static definition or perhaps dynamically from the users database role itself.

  1. class Default_Model_User implements Zend_Acl_Role_Interface
  2. {
  3.     protected $_aclRoleId = null;
  4.
  5.     public function getRoleId()
  6.     {
  7.         if ($this->_aclRoleId == null) {
  8.             return 'guest';
  9.         }
  10.
  11.         return $this->_aclRoleId;
  12.     }
  13. }

While the concept of a user as a role is pretty straight forward, your application might choose to have any other models in your system as a potential "resource" to be consumed in this ACL system. For simplicity, we'll use the example of a blog post. Since the type of the resource is tied to the type of the object, this class will only return 'blogPost' as the resource ID in this system. Naturally, this value can be dynamic if your system requires it to be so.

  1. class Default_Model_BlogPost implements Zend_Acl_Resource_Interface
  2. {
  3.     public function getResourceId()
  4.     {
  5.         return 'blogPost';
  6.     }
  7. }

Now that we have at least a role and a resource, we can go about defining the rules of the ACL system. These rules will be consulted when the system receives a query about what is possible given a certain role, resources, and optionally a privilege.

Lets assume the following rules:

  1. $acl = new Zend_Acl();
  2.
  3. // setup the various roles in our system
  4. $acl->addRole('guest');
  5. // owner inherits all of the rules of guest
  6. $acl->addRole('owner', 'guest');
  7.
  8. // add the resources
  9. $acl->addResource('blogPost');
  10.
  11. // add privileges to roles and resource combinations
  12. $acl->allow('guest', 'blogPost', 'view');
  13. $acl->allow('owner', 'blogPost', 'post');
  14. $acl->allow('owner', 'blogPost', 'publish');

The above rules are quite simple: a guest role and an owner role exist; as does a blogPost type resource. Guests are allowed to view blog posts, and owners are allowed to post and publish blog posts. To query this system one might do any of the following:

  1. // assume the user model is of type guest resource
  2. $guestUser = new Default_Model_User();
  3. $ownerUser = new Default_Model_Owner('OwnersUsername');
  4.
  5. $post = new Default_Model_BlogPost();
  6.
  7. $acl->isAllowed($guestUser, $post, 'view'); // true
  8. $acl->isAllowed($ownerUser, $post, 'view'); // true
  9. $acl->isAllowed($guestUser, $post, 'post'); // false
  10. $acl->isAllowed($ownerUser, $post, 'post'); // true

As you can see, the above rules exercise whether owners and guests can view posts, which they can, or post new posts, which owners can and guests cannot. But as you might expect this type of system might not be as dynamic as we wish it to be. What if we want to ensure a specific owner actual owns a very specific blog post before allowing him to publish it? In other words, we want to ensure that only post owners have the ability to publish their own posts.

This is where assertions come in. Assertions are methods that will be called out to when the static rule checking is simply not enough. When registering an assertion object this object will be consulted to determine, typically dynamically, if some roles has access to some resource, with some optional privlidge that can only be answered by the logic within the assertion. For this example, we'll use the following assertion:

  1. class OwnerCanPublishBlogPostAssertion implements Zend_Acl_Assert_Interface
  2. {
  3.     /**
  4.      * This assertion should receive the actual User and BlogPost objects.
  5.      *
  6.      * @param Zend_Acl $acl
  7.      * @param Zend_Acl_Role_Interface $user
  8.      * @param Zend_Acl_Resource_Interface $blogPost
  9.      * @param $privilege
  10.      * @return bool
  11.      */
  12.     public function assert(Zend_Acl $acl,
  13.                            Zend_Acl_Role_Interface $user = null,
  14.                            Zend_Acl_Resource_Interface $blogPost = null,
  15.                            $privilege = null)
  16.     {
  17.         if (!$user instanceof Default_Model_User) {
  18.             throw new Exception(__CLASS__
  19.                               . '::'
  20.                               . __METHOD__
  21.                               . ' expects the role to be'
  22.                               . ' an instance of User');
  23.         }
  24.
  25.         if (!$blogPost instanceof Default_Model_BlogPost) {
  26.             throw new Exception(__CLASS__
  27.                               . '::'
  28.                               . __METHOD__
  29.                               . ' expects the resource to be'
  30.                               . ' an instance of BlogPost');
  31.         }
  32.
  33.         // if role is publisher, he can always modify a post
  34.         if ($user->getRoleId() == 'publisher') {
  35.             return true;
  36.         }
  37.
  38.         // check to ensure that everyone else is only modifying their own post
  39.         if ($user->id != null && $blogPost->ownerUserId == $user->id) {
  40.             return true;
  41.         } else {
  42.             return false;
  43.         }
  44.     }
  45. }

To hook this into our ACL system, we would do the following:

  1. // replace this:
  2. //   $acl->allow('owner', 'blogPost', 'publish');
  3. // with this:
  4. $acl->allow('owner',
  5.             'blogPost',
  6.             'publish',
  7.             new OwnerCanPublishBlogPostAssertion());
  8.
  9. // lets also add the role of a "publisher" who has access to everything
  10. $acl->allow('publisher', 'blogPost', 'publish');

Now, anytime the ACL is consulted about whether or not an owner can publish a specific blog post, this assertion will be run. This assertion will ensure that unless the role type is 'publisher' the owner role must be logically tied to the blog post in question. In this example, we check to see that the ownerUserId property of the blog post matches the id of the owner passed in.

Authenticating Users in Zend Framework
Getting Started with Zend_Session, Zend_Auth, and Zend_Acl
Zend Framework手册 中文版
Getting Started with Zend_Search_Lucene
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Getting Started with Zend_Session, Zend_Auth, and Zend_Acl
  • Building Multi-User Applications With Zend Framework
  • Managing User Sessions In ZF
  • Authenticating Users in Zend Framework
  • Building an Authorization System in Zend Framework


Getting Started with Zend_Paginator - Zend Framework Manual

Search result pagination
Learning Zend Framework
Zend Framework手册 中文版
Introduction

Getting Started with Zend_Paginator

Table of Contents
  • Introduction
  • Simple Examples
  • Pagination Control and ScrollingStyles
  • Putting it all Together
Search result pagination
Learning Zend Framework
Zend Framework手册 中文版
Introduction
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Zend Framework Quick Start
  • Autoloading in Zend Framework
  • Plugins in Zend Framework
  • Getting Started with Zend_Layout
  • Getting Started Zend_View Placeholders
  • Understanding and Using Zend Form Decorators
  • Getting Started with Zend_Session, Zend_Auth, and Zend_Acl
  • Getting Started with Zend_Search_Lucene
  • Getting Started with Zend_Paginator


Introduction - Zend Framework Manual

Getting Started with Zend_Paginator
Getting Started with Zend_Paginator
Zend Framework手册 中文版
Simple Examples

Introduction

Let's say you're creating a blogging application that will be home to your vast collection of blog posts. There is a good chance that you do not want all of your blog posts to appear on one single page when someone visits your blog. An obvious solution would be to only display a small number of blog posts on the screen at a time, and allow the user to browse through the different pages, much like your favorite search engine shows you the result of your search query. Zend_Paginator is designed to help you achieve the goal of dividing collections of data in smaller, more manageable sets more easily, with more consistency, and with less duplicate code.

Zend_Paginator uses Adapters to support various data sources and ScrollingStyles to support various methods of showing the user which pages are available. In later sections of this text we will have a closer look at what these things are and how they can help you to make the most out of Zend_Paginator.

Before going in-depth, we will have a look at some simple examples first. After these simple examples, we will see how Zend_Paginator supports the most common use-case; paginating database results.

This introduction has given you a quick overview of Zend_Paginator. To get started and to have a look at some code snippets, let's have a look at some simple examples.

Getting Started with Zend_Paginator
Getting Started with Zend_Paginator
Zend Framework手册 中文版
Simple Examples
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Getting Started with Zend_Paginator
  • Introduction
  • Simple Examples
  • Pagination Control and ScrollingStyles
  • Putting it all Together


Simple Examples - Zend Framework Manual

Introduction
Getting Started with Zend_Paginator
Zend Framework手册 中文版
Pagination Control and ScrollingStyles

Simple Examples

In this first example we won't do anything spectacular, but hopefully it will give you a good idea of what Zend_Paginator is designed to do. Let's say we have an array called $data with the numbers 1 to 100 in it, which we want to divide over a number of pages. We can use the static factory() method in the Zend_Paginator class to get a Zend_Paginator object with our array in it.

  1. // Create an array with numbers 1 to 100
  2. $data = range(1, 100);
  3.
  4. // Get a Paginator object using Zend_Paginator's built-in factory.
  5. $paginator = Zend_Paginator::factory($data);

We're already almost done! The $paginator variable now contains a reference to the Paginator object. By default it is setup to display 10 items per page. To display the items for the currently active page, all you need to do is iterate over the Paginator object with a foreach loop. The currently active page defaults to the first page if it's not explicitly specified. We will see how you can select a specific page later on. The snippet below will display an unordered list containing the numbers 1 to 10, which are the numbers on the first page.

  1. // Create an array with numbers 1 to 100
  2. $data = range(1, 100);
  3.
  4. // Get a Paginator object using Zend_Paginator's built-in factory.
  5. $paginator = Zend_Paginator::factory($data);
  6.
  7. ?><ul><?php
  8.
  9. // Render each item for the current page in a list-item
  10. foreach ($paginator as $item) {
  11.     echo '<li>' . $item . '</li>';
  12. }
  13.
  14. ?></ul>

Now let's try and render the items on the second page. You can use the setCurrentPageNumber() method to select which page you want to view.

  1. // Create an array with numbers 1 to 100
  2. $data = range(1, 100);
  3.
  4. // Get a Paginator object using Zend_Paginator's built-in factory.
  5. $paginator = Zend_Paginator::factory($data);
  6.
  7. // Select the second page
  8. $paginator->setCurrentPageNumber(2);
  9.
  10. ?><ul><?php
  11.
  12. // Render each item for the current page in a list-item
  13. foreach ($paginator as $item) {
  14.     echo '<li>' . $item . '</li>';
  15. }
  16.
  17. ?></ul>

As expected, this little snippet will render an unordered list with the numbers 11 to 20 in it.

These simple examples demonstrate a small portion of what can be achieved with Zend_Paginator. However, a real application rarely reads its data from a plain array, so the next section is dedicated to showing you how you can use Paginator to paginate the results of a database query. Before reading on, make sure you're familiar with the way Zend_Db_Select works!

In the database examples we will look at a table with blog posts called 'posts'. The 'posts' table has four columns: id, title, body, date_created. Let's dive right in and have a look at a simple example.

  1. // Create a select query. $db is a Zend_Db_Adapter object, which we assume
  2. // already exists in your script.
  3. $select = $db->select()->from('posts')->order('date_created DESC');
  4.
  5. // Get a Paginator object using Zend_Paginator's built-in factory.
  6. $paginator = Zend_Paginator::factory($select);
  7.
  8. // Select the second page
  9. $paginator->setCurrentPageNumber(2);
  10.
  11. ?><ul><?php
  12.
  13. // Render each the title of each post for the current page in a list-item
  14. foreach ($paginator as $item) {
  15.     echo '<li>' . $item->title . '</li>';
  16. }
  17.
  18. ?></ul>

As you can see, this example is not that different from the previous one. The only difference is that you pass a Zend_Db_Select object to the Paginator's factory() method, rather than an array. For more details on how the database adapter makes sure that your query is being executed efficiently, see the Zend_Paginator chapter in the reference manual on the DbSelect and DbTableSelect adapters.

Introduction
Getting Started with Zend_Paginator
Zend Framework手册 中文版
Pagination Control and ScrollingStyles
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Getting Started with Zend_Paginator
  • Introduction
  • Simple Examples
  • Pagination Control and ScrollingStyles
  • Putting it all Together


Pagination Control and ScrollingStyles - Zend Framework Manual

Simple Examples
Getting Started with Zend_Paginator
Zend Framework手册 中文版
Putting it all Together

Pagination Control and ScrollingStyles

Rendering the items for a page on the screen has been a good start. In the code snippets in previous section we have also seen the setCurrentPageNumber() method to set the active page number. The next step is to navigate through your pages. To do this, Paginator provides you with two important tools: the ability to render the Paginator with help of a View Partial, and support for so-called ScrollingStyles.

The View Partial is a small view script that renders the Pagination controls, such as buttons to go to the next or previous page. Which pagination controls are rendered depends on the contents of the view partial. Working with the view partial requires that you have set up Zend_View. To get started with the pagination control, create a new view script somewhere in your view scripts path. You can name it anything you want, but we'll call it "controls.phtml" in this text. The reference manual contains various examples of what might go in the view script. Here is one example.

  1. <?php if ($this->pageCount): ?>
  2. <!-- First page link -->
  3. <?php if (isset($this->previous)): ?>
  4.   <a href="<?php echo $this->url(array('page' => $this->first)); ?>">
  5.     First
  6.   </a> |
  7. <?php else: ?>
  8.   <span class="disabled">First</span> |
  9. <?php endif; ?>
  10.
  11. <!-- Previous page link -->
  12. <?php if (isset($this->previous)): ?>
  13.   <a href="<?php echo $this->url(array('page' => $this->previous)); ?>">
  14.     &lt; Previous
  15.   </a> |
  16. <?php else: ?>
  17.   <span class="disabled">&lt; Previous</span> |
  18. <?php endif; ?>
  19.
  20. <!-- Next page link -->
  21. <?php if (isset($this->next)): ?>
  22.   <a href="<?php echo $this->url(array('page' => $this->next)); ?>">
  23.     Next &gt;
  24.   </a> |
  25. <?php else: ?>
  26.   <span class="disabled">Next &gt;</span> |
  27. <?php endif; ?>
  28.
  29. <!-- Last page link -->
  30. <?php if (isset($this->next)): ?>
  31.   <a href="<?php echo $this->url(array('page' => $this->last)); ?>">
  32.     Last
  33.   </a>
  34. <?php else: ?>
  35.   <span class="disabled">Last</span>
  36. <?php endif; ?>
  37.
  38. </div>
  39. <?php endif; ?>

The next step is to tell Zend_Paginator which view partial can be used to render the navigation controls. Put the following line in your application's bootstrap file.

  1. Zend_View_Helper_PaginationControl::setDefaultViewPartial('controls.phtml');

The last step is probably the easiest. Make sure you have assigned your Paginator object to the a script (NOT the 'controls.phtml' script!). The only thing left to do is echo the Paginator in the view script. This will automatically render the Paginator using the PaginationControl view helper. In this next example, the Paginator object has been assigned to the 'paginator' view variable. Don't worry if you don't fully get how it all works yet. The next section will feature a complete example.

  1. <?php echo $this->paginator; ?>

Zend_Paginator, together with the 'controls.phtml' view script you wrote, makes sure your Paginator navigation is rendered properly. In order to decide which page numbers need to be displayed on screen, Paginator uses so-called ScrollingStyles. The default style is called "Sliding", which is similar to the way Yahoo's search result navigation works. To mimick Google's ScrollingStyle, use the Elastic style. You can set a default ScrollingStyle with the static setDefaultScrollingStyle() method, or you can specify a ScrollingStyle dynamically when rendering the Paginator in your view script. This requires manual invocation of the view helper in your view script.

  1. // $this->paginator is a Paginator object
  2. <?php echo $this->paginationControl($this->paginator, 'Elastic', 'controls.phtml'); ?>

For a list of all available ScrollingStyles, see the reference manual.

Simple Examples
Getting Started with Zend_Paginator
Zend Framework手册 中文版
Putting it all Together
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Getting Started with Zend_Paginator
  • Introduction
  • Simple Examples
  • Pagination Control and ScrollingStyles
  • Putting it all Together


Putting it all Together - Zend Framework Manual

Pagination Control and ScrollingStyles
Getting Started with Zend_Paginator
Zend Framework手册 中文版
Zend Framework Reference

Putting it all Together

You have seen how to create a Paginator object, how to render the items on the current page, and how to render a navigation element to browse through your pages. In this section you will see how Paginator fits in with the rest of your MVC application.

In the following examples we will ignore the best practice implementation of using a Service Layer to keep the example simple and easier to understand. Once you get familiar with using Service Layers, it should be easy to see how Paginator can fit in with the best practice approach.

Lets start with the controller. The sample application is simple, and we'll just put everything in the IndexController and the IndexAction. Again, this is for demonstration purposes only. A real application should not use controllers in this manner.

  1. class IndexController extends Zend_Controller_Action
  2. {
  3.     public function indexAction()
  4.     {
  5.         // Setup pagination control view script. See the pagation control tutorial page
  6.         // for more information about this view script.
  7.         Zend_View_Helper_PaginationControl::setDefaultViewPartial('controls.phtml');
  8.
  9.         // Fetch an already instantiated database connection from the registry
  10.         $db = Zend_Registry::get('db');
  11.
  12.         // Create a select object which fetches blog posts, sorted decending by date of creation
  13.         $select = $db->select()->from('posts')->sort('date_created DESC');
  14.
  15.         // Create a Paginator for the blog posts query
  16.         $paginator = Zend_Paginator::factory($select);
  17.
  18.         // Read the current page number from the request. Default to 1 if no explicit page number is provided.
  19.         $paginator->setCurrentPageNumber($this->_getParam('page', 1));
  20.
  21.         // Assign the Paginator object to the view
  22.         $this->view->paginator = $paginator;
  23.     }
  24. }

The following view script is the index.phtml view script for the IndexController's indexAction. The view script can be kept simple. We're assuming the use of the default ScrollingStyle.

  1. <ul>
  2. <?php
  3. // Render each the title of each post for the current page in a list-item
  4. foreach ($this->paginator as $item) {
  5.     echo '<li>' . $item->title . '</li>';
  6. }
  7. ?>
  8. </ul>
  9. <?php echo $this->paginator; ?>

Now navigate to your project's index and see Paginator in action. What we have discussed in this tutorial is just the tip of the iceberg. The reference manual and API documentation can tell you more about what you can do with Zend_Paginator.

Pagination Control and ScrollingStyles
Getting Started with Zend_Paginator
Zend Framework手册 中文版
Zend Framework Reference
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Getting Started with Zend_Paginator
  • Introduction
  • Simple Examples
  • Pagination Control and ScrollingStyles
  • Putting it all Together


Getting Started Zend_View Placeholders - Zend Framework Manual

Zend_Layout: Conclusions
Learning Zend Framework
Zend Framework手册 中文版
Introduction

Getting Started Zend_View Placeholders

Table of Contents
  • Introduction
  • Basic Placeholder Usage
  • Standard Placeholders
  • View Placeholders: Conclusion
Zend_Layout: Conclusions
Learning Zend Framework
Zend Framework手册 中文版
Introduction
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Zend Framework Quick Start
  • Autoloading in Zend Framework
  • Plugins in Zend Framework
  • Getting Started with Zend_Layout
  • Getting Started Zend_View Placeholders
  • Understanding and Using Zend Form Decorators
  • Getting Started with Zend_Session, Zend_Auth, and Zend_Acl
  • Getting Started with Zend_Search_Lucene
  • Getting Started with Zend_Paginator


Introduction - Zend Framework Manual

Getting Started Zend_View Placeholders
Getting Started Zend_View Placeholders
Zend Framework手册 中文版
Basic Placeholder Usage

Introduction

In the previous chapter, we looked at primarily the Two Step View pattern, which allows you to embed individual application views within a sitewide layout. At the end of that chapter, however, we discussed some limitations:

  • How do you alter the page title?

  • How would you inject conditional scripts or stylesheets into the sitewide layout?

  • How would you create and render an optional sidebar? What if there was some content that was unconditional, and other content that was conditional for the sidebar?

These questions are addressed in the » Composite View design pattern. One approach to that pattern is to provide "hints" or content to the sitewide layout. In Zend Framework, this is achieved through specialized view helpers called "placeholders." Placeholders allow you to aggregate content, and then render that aggregate content elsewhere.

Getting Started Zend_View Placeholders
Getting Started Zend_View Placeholders
Zend Framework手册 中文版
Basic Placeholder Usage
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Getting Started Zend_View Placeholders
  • Introduction
  • Basic Placeholder Usage
  • Standard Placeholders
  • View Placeholders: Conclusion


Basic Placeholder Usage - Zend Framework Manual

Introduction
Getting Started Zend_View Placeholders
Zend Framework手册 中文版
Standard Placeholders

Basic Placeholder Usage

Zend Framework defines a generic placeholder() view helper that you may use for as many custom placeholders you need. It also provides a variety of specific placeholder implementations for often-needed functionality, such as specifying the DocType declaration, document title, and more.

All placeholders operate in roughly the same way. They are containers, and thus allow you to operate on them as collections. With them you can:

  • Append or prepend items to the collection.

  • Replace the entire collection with a single value.

  • Specify a string with which to prepend output of the collection when rendering.

  • Specify a string with which to append output of the collection when rendering.

  • Specify a string with which to separate items of the collection when rendering.

  • Capture content into the collection.

  • Render the aggregated content.

Typically, you will call the helper with no arguments, which will return a container on which you may operate. You will then either echo this container to render it, or call methods on it to configure or populate it. If the container is empty, rendering it will simply return an empty string; otherwise, the content will be aggregated according to the rules by which you configure it.

As an example, let's create a sidebar that consists of a number of "blocks" of content. You'll likely know up-front the structure of each block; let's assume for this example that it might look like this:

  1. <div class="sidebar">
  2.     <div class="block">
  3.         <p>
  4.             Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus
  5.             consectetur aliquet odio ac consectetur. Nulla quis eleifend
  6.             tortor. Pellentesque varius, odio quis bibendum consequat, diam
  7.             lectus porttitor quam, et aliquet mauris orci eu augue.
  8.         </p>
  9.     </div>
  10.     <div class="block">
  11.         <ul>
  12.             <li><a href="/some/target">Link</a></li>
  13.             <li><a href="/some/target">Link</a></li>
  14.         </ul>
  15.     </div>
  16. </div>

The content will vary based on the controller and action, but the structure will be the same. Let's first setup the sidebar in a resource method of our bootstrap:

  1. class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
  2. {
  3.     // ...
  4.
  5.     protected function _initSidebar()
  6.     {
  7.         $this->bootstrap('View');
  8.         $view = $this->getResource('View');
  9.
  10.         $view->placeholder('sidebar')
  11.              // "prefix" -> markup to emit once before all items in collection
  12.              ->setPrefix("<div class=\"sidebar\">\n    <div class=\"block\">\n")
  13.              // "separator" -> markup to emit between items in a collection
  14.              ->setSeparator("</div>\n    <div class=\"block\">\n")
  15.              // "postfix" -> markup to emit once after all items in a collection
  16.              ->setPostfix("</div>\n</div>");
  17.     }
  18.
  19.     // ...
  20. }

The above defines a placeholder, "sidebar", that has no items. It configures the basic markup structure of that placeholder, however, per our requirements.

Now, let's assume for the "user" controller that for all actions we'll want a block at the top containing some information. We could accomplish this in two ways: (a) we could add the content to the placeholder directly in the controller's preDispatch() method, or (b) we could render a view script from within the preDispatch() method. We'll use (b), as it follows a more proper separation of concerns (leaving view-related logic and functionality within a view script).

We'll name the view script "user/_sidebar.phtml", and populate it as follows:

  1. <?php $this->placeholder('sidebar')->captureStart() ?>
  2. <h4>User Administration</h4>
  3. <ul>
  4.     <li><a href="<?php $this->url(array('action' => 'list')) ?>">
  5.         List</a></li>
  6.     <li><a href="<?php $this->url(array('action' => 'create')) ?>">
  7.         Create</a></a></li>
  8. </ul>
  9. <?php $this->placeholder('sidebar')->captureEnd() ?>

The above example makes use of the content capturing feature of placeholders. By default, content is appended as a new item in the container, allowing us to aggregate content. This example makes use of view helpers and static HTML in order to generate markup, and the content is then captured and appended into the placeholder itself.

To invoke the above view script, we would write the following in our preDispatch() method:

  1. class UserController extends Zend_Controller_Action
  2. {
  3.     // ...
  4.
  5.     public function preDispatch()
  6.     {
  7.         // ...
  8.
  9.         $this->view->render('user/_sidebar.phtml');
  10.
  11.         // ...
  12.     }
  13.
  14.     // ...
  15. }

Note that we're not capturing the rendered value; there's no need, as the entierty of that view is being captured into a placeholder.

Now, let's assume our "view" action in that same controller needs to present some information. Within the "user/view.phtml" view script, we might have the following snippet of content:

  1. $this->placeholder('sidebar')
  2.      ->append('<p>User: ' . $this->escape($this->username) .  '</p>');

This example makes use of the append() method, and passes it some simple markup to aggregate.

Finally, let's modify our layout view script, and have it render the placeholder.

  1. <html>
  2. <head>
  3.     <title>My Site</title>
  4. </head>
  5. <body>
  6.     <div class="content">
  7.         <?php echo $this->layout()->content ?>
  8.     </div>
  9.     <?php echo $this->placeholder('sidebar') ?>
  10. </body>
  11. </html>

For controllers and actions that do not populate the "sidebar" placeholder, no content will be rendered; for those that do, however, echoing the placeholder will render the content according to the rules we created in our bootstrap, and the content we aggregated throughout the application. In the case of the "/user/view" action, and assuming a username of "matthew", we would get content for the sidebar as follows (formatted for readability):

  1. <div class="sidebar">
  2.     <div class="block">
  3.         <h4>User Administration</h4>
  4.         <ul>
  5.             <li><a href="/user/list">List</a></li>
  6.             <li><a href="/user/create">Create</a></a></li>
  7.         </ul>
  8.     </div>
  9.     <div class="block">
  10.         <p>User: matthew</p>
  11.     </div>
  12. </div>

There are a large number of things you can do by combining placeholders and layout scripts; experiment with them, and read the relevant manual sections for more information.

Introduction
Getting Started Zend_View Placeholders
Zend Framework手册 中文版
Standard Placeholders
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Getting Started Zend_View Placeholders
  • Introduction
  • Basic Placeholder Usage
  • Standard Placeholders
  • View Placeholders: Conclusion


Standard Placeholders - Zend Framework Manual

Basic Placeholder Usage
Getting Started Zend_View Placeholders
Zend Framework手册 中文版
View Placeholders: Conclusion

Standard Placeholders

In the previous section, we learned about the placeholder() view helper, and how it can be used to aggregate custom content. In this section, we'll look at some of the concrete placeholders shipped with Zend Framework, and how you can use them to your advantage when creating complex composite layouts.

Most of the shipped placeholders are for generating content for the <head> section of your layout content -- an area you typically cannot manipulate directly via your application view scripts, but one you may want to influence. As examples: you may want your title to contain certain content on every page, but specific content based on the controller and/or action; you may want to specify CSS files to load based on what section of the application you're in; you may need specific JavaScript scripts loaded at different times; or you may want to set the DocType declaration.

Zend Framework ships with placeholder implementations for each of these situations, and several more.

Setting the DocType

DocType declarations are troublesome to memorize, and often essential to include in your document to ensure the browser properly renders your content. The doctype() view helper allows you to use simple string mnemonics to specify the desired DocType; additionally, other helpers will query the doctype() helper to ensure the output generated conforms with the requested DocType.

As an example, if you want to use the XHTML1 Strict DTD, you can simply specify:

  1. $this->doctype('XHTML1_STRICT');

Among the other available mnemonics, you'll find these common types:

XHTML1_STRICT

XHTML 1.0 Strict

XHTML1_TRANSITIONAL

XHTML 1.0 Transitional

HTML4_STRICT

HTML 4.01 Strict

HTML4_Loose

HTML 4.01 Loose

HTML5

HTML 5

You can assign the type and render the declaration in a single call:

  1. echo $this->doctype('XHTML1_STRICT');

However, the better approach is to assign the type in your bootstrap, and then render it in your layout. Try adding the following to your bootstrap class:

  1. class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
  2. {
  3.     protected function _initDocType()
  4.     {
  5.         $this->bootstrap('View');
  6.         $view = $this->getResource('View');
  7.         $view->doctype('XHTML1_STRICT');
  8.     }
  9. }

Then, in your layout script, simply echo the helper at the top of the file:

  1. <?php echo $this->doctype() ?>
  2. <html>
  3.     <!-- ... -->

This will ensure that your DocType-aware view helpers render the appropriate markup, ensure that the type is set well before the layout is rendered, and provide a single location to change the DocType.

Specifying the Page Title

Often, a site will include the site or business name as part of the page title, and then add additional information based on the location within the site. As an example, the zend.com website includes the string "Zend.com" on all pages, and the prepends information based on the page: "Zend Server - Zend.com". Within Zend Framework, the headTitle() view helper can help simplify this task.

At its simplest, the headTitle() helper allows you to aggregate content for the <title> tag; when you echo it, it then assembles it based on the order in which segments are added. You can control the order using prepend() and append(), and provide a separator to use between segments using the setSeparator() method.

Typically, you should specify any segments common to all pages in your bootstrap, similar to how we define the doctype. In this case, we'll define a _initPlaceholders() method for operating on all the various placeholders, and specify an initial title as well as a separator.

  1. class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
  2. {
  3.     // ...
  4.
  5.     protected function _initPlaceholders()
  6.     {
  7.         $this->bootstrap('View');
  8.         $view = $this->getResource('View');
  9.         $view->doctype('XHTML1_STRICT');
  10.
  11.         // Set the initial title and separator:
  12.         $view->headTitle('My Site')
  13.              ->setSeparator(' :: ');
  14.     }
  15.
  16.     // ...
  17. }

Within a view script, we might want to add another segment:

  1. <?php $this->headTitle()->append('Some Page'); // place after other segments ?>
  2. <?php $this->headTitle()->prepend('Some Page'); // place before ?>

In our layout, we will simply echo the headTitle() helper:

  1. <?php echo $this->doctype() ?>
  2. <html>
  3.     <?php echo $this->headTitle() ?>
  4.     <!-- ... -->

This will generate the following output:

  1. <!-- If append() was used: -->
  2. <title>My Site :: Some Page</title>
  3.
  4. <!-- If prepend() was used: -->
  5. <title>Some Page :: My Site</title>

Specifying Stylesheets with HeadLink

Good CSS developers will often create a general stylesheet for sitewide styles, and individual stylesheets for specific sections or pages of the website, and load these latter conditionally so as to decrease the amount of data needing to be transferred on each request. The headLink() placeholder makes such conditional aggregation of stylesheets trivial within your application.

To accomplish this, headLink() defines a number of "virtual" methods (via overloading) to make the process trivial. The ones we will be concerned with are appendStylesheet() and prependStylesheet(). Each takes up to four arguments, $href (the relative path to the stylesheet), $media (the MIME type, which defaults to "text/css"), $conditionalStylesheet (which can be used to specify a "condition" under which the stylesheet will be evaluated), and $extras (an associative array of key and value pairs, commonly used to specify a key for "media"). In most cases, you will only need to specify the first argument, the relative path to the stylesheet.

In our example, we'll assume that all pages need to load the stylesheet located in "/styles/site.css" (relative to the document root); we'll specify this in our _initPlaceholders() bootstrap method.

  1. class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
  2. {
  3.     // ...
  4.
  5.     protected function _initPlaceholders()
  6.     {
  7.         $this->bootstrap('View');
  8.         $view = $this->getResource('View');
  9.         $view->doctype('XHTML1_STRICT');
  10.
  11.         // Set the initial title and separator:
  12.         $view->headTitle('My Site')
  13.              ->setSeparator(' :: ');
  14.
  15.         // Set the initial stylesheet:
  16.         $view->headLink()->prependStylesheet('/styles/site.css');
  17.     }
  18.
  19.     // ...
  20. }

Later, in a controller or action-specific view script, we can add more stylesheets:

  1. <?php $this->headLink()->appendStylesheet('/styles/user-list.css') ?>

Within our layout view script, once again, we simply echo the placeholder:

  1. <?php echo $this->doctype() ?>
  2. <html>
  3.     <?php echo $this->headTitle() ?>
  4.     <?php echo $this->headLink() ?>
  5.     <!-- ... -->

This will generate the following output:

  1. <link rel="stylesheet" type="text/css" href="/styles/site.css" />
  2. <link rel="stylesheet" type="text/css" href="/styles/user-list.css" />

Aggregating Scripts Using HeadScript

Another common tactic to prevent long page load times is to only load JavaScript when necessary. That said, you may need several layers of scripts: perhaps one for progressively enhancing menus on the site, and another for page-specific content. In these situations, the headScript() helper presents a solution.

Similar to the headLink() helper, headScript() provides the ability to append or prepend scripts to the collection, and then echo the entire set. It provides the flexibility to specify either script files themselves to load, or explicit JavaScript. You also have the option of capturing JavaScript via captureStart()/ captureEnd(), which allows you to simply inline the JavaScript instead of requiring an additional call to your server.

Also like headLink(), headScript() provides "virtual" methods via overloading as a convenience when specifying items to aggregate; common methods include prependFile(), appendFile(), prependScript(), and appendScript(). The first two allow you to specify files that will be referenced in a <script> tag's $src attribute; the latter two will take the content provided and render it as literal JavaScript within a <script> tag.

In this example, we'll specify that a script, "/js/site.js" needs to be loaded on every page; we'll update our _initPlaceholders() bootstrap method to do this.

  1. class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
  2. {
  3.     // ...
  4.
  5.     protected function _initPlaceholders()
  6.     {
  7.         $this->bootstrap('View');
  8.         $view = $this->getResource('View');
  9.         $view->doctype('XHTML1_STRICT');
  10.
  11.         // Set the initial title and separator:
  12.         $view->headTitle('My Site')
  13.              ->setSeparator(' :: ');
  14.
  15.         // Set the initial stylesheet:
  16.         $view->headLink()->prependStylesheet('/styles/site.css');
  17.
  18.         // Set the initial JS to load:
  19.         $view->headScript()->prependFile('/js/site.js');
  20.     }
  21.
  22.     // ...
  23. }

Within a view script, we might then add an extra script file to source, or capture some JavaScript to include in our document.

  1. <?php $this->headScript()->appendFile('/js/user-list.js') ?>
  2. <?php $this->headScript()->captureStart() ?>
  3. site = {
  4.     baseUrl: "<?php echo $this->baseUrl() ?>"
  5. };
  6. <?php $this->headScript()->captureEnd() ?>

Within our layout script, we then simply echo the placeholder, just as we have all the others:

  1. <?php echo $this->doctype() ?>
  2. <html>
  3.     <?php echo $this->headTitle() ?>
  4.     <?php echo $this->headLink() ?>
  5.     <?php echo $this->headScript() ?>
  6.     <!-- ... -->

This will generate the following output:

  1. <script type="text/javascript" src="/js/site.js"></script>
  2. <script type="text/javascript" src="/js/user-list.js"></script>
  3. <script type="text/javascript">
  4. site = {
  5.     baseUrl: "<?php echo $this->baseUrl() ?>"
  6. };
  7. </script>

Note: InlineScript Variant
 Many browsers will often block display of a page until all scripts and stylesheets referenced in the <head> section have loaded. If you have a number of such directives, this can impact how soon somebody can start actually viewing the page.
One way around this is to emit your <script> tags just prior to closing the <body> of your document. (This is a practice specifically recommend by the » Y! Slow project.)
Zend Framework supports this in two different ways:

  • You can render your headScript() tag whereever you like in your layout script; just because the title references "head" does not mean it needs to be rendered in that location.

  • Alternately, you may use the inlineScript() helper, which is simply a variant on headScript(), and retains the same behavior, but uses a separate registry.

Basic Placeholder Usage
Getting Started Zend_View Placeholders
Zend Framework手册 中文版
View Placeholders: Conclusion
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Getting Started Zend_View Placeholders
  • Introduction
  • Basic Placeholder Usage
  • Standard Placeholders
  • View Placeholders: Conclusion


View Placeholders: Conclusion - Zend Framework Manual

Standard Placeholders
Getting Started Zend_View Placeholders
Zend Framework手册 中文版
Understanding and Using Zend Form Decorators

View Placeholders: Conclusion

View placeholders are a simple and powerful method for creating rich layouts for your application. You can use a variety of standard placeholders, such as those discussed ( doctype(), headTitle(), headLink(), and headScript()), or use the generic placeholder() helper to aggregate content and render it in custom ways. Experiment with their exposed functionality, and visit the appropriate sections in the reference guide to find out about the additional features they offer -- and how you may leverage those features to create rich content for your readers.

Standard Placeholders
Getting Started Zend_View Placeholders
Zend Framework手册 中文版
Understanding and Using Zend Form Decorators
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Learning Zend Framework
  • Getting Started Zend_View Placeholders
  • Introduction
  • Basic Placeholder Usage
  • Standard Placeholders
  • View Placeholders: Conclusion


Zend Framework Reference - Zend Framework Manual

Putting it all Together
Zend_Acl

Zend Framework Reference

Table of Contents
  • Zend_Acl
    • 简介
    • 精细的访问控制
    • 高级用法
  • Zend_Amf
    • Introduction
    • Zend_Amf_Server
  • Zend_Application
    • 简介
    • Zend_Application Quick Start
    • Theory of Operation
    • Examples
    • Core Functionality
    • Available Resource Plugins
  • Zend_Auth
    • 简介
    • 数据库表认证
    • 摘要式认证
    • HTTP 认证适配器
    • LDAP 认证
    • Open ID Authentication
  • Zend_Barcode
    • Introduction
    • Barcode creation using Zend_Barcode class
    • Zend_Barcode Objects
    • Zend_Barcode Renderers
  • Zend_Cache
    • 简介
    • 缓存原理
    • Zend_Cache前端
    • Zend_Cache后端
    • The Cache Manager
  • Zend_Captcha
    • 简介
    • Captcha 操作
    • Captcha 适配器
  • Zend_CodeGenerator
    • Introduction
    • Zend_CodeGenerator Examples
    • Zend_CodeGenerator Reference
  • Zend_Config
    • 简介
    • 操作理论
    • Zend_Config_Ini
    • Zend_Config_Xml
  • Zend_Config_Writer
    • Zend_Config_Writer
  • Zend_Console_Getopt
    • Getopt 简介
    • 声明 Getopt 规则
    • 读取（Fetching）选项和参数
    • 配置 Zend_Console_Getopt
  • Zend_Controller
    • Zend_Controller 快速入门
    • Zend_Controller 基础
    • 前端控制器
    • 请求对象
    • 标准路由器
    • 分发器
    • 动作控制器
    • 动作助手
    • 响应对象
    • 插件
    • 使用传统的模块目录结构
    • MVC 异常
  • Zend_Currency
    • Zend_Currency 简介
    • 如何使用货币
    • Options for currencies
    • What makes a currency?
    • Where is the currency?
    • How does the currency look like?
    • How much is my currency?
    • Calculating with currencies
    • Exchanging currencies
    • Additional informations on Zend_Currency
  • Zend_Date
    • 简介
    • 操作理论
    • 基本方法
    • Zend_Date API 概述
    • 生成日期
    • 一般日期函数的常量
    • Working 范例
  • Zend_Db
    • Zend_Db_Adapter
    • Zend_Db_Statement
    • Zend_Db_Profiler
    • Zend_Db_Select
    • Zend_Db_Table
    • Zend_Db_Table_Row
    • Zend_Db_Table_Rowset
    • Zend_Db_Table Relationships
    • Zend_Db_Table_Definition
  • Zend_Debug
    • 输出变量的值 (Dumping Variables)
  • Zend_Dojo
    • 简介
    • Zend_Dojo_Data: dojo.data Envelopes
    • Dojo 视图助手
    • Dojo 表单元素和装饰器
    • Zend_Dojo build layer support
  • Zend_Dom
    • 简介
    • Zend_Dom_Query
  • Zend_Exception
    • 使用“异常”
    • Basic usage
    • Previous Exceptions
  • Zend_Feed
    • 介绍
    • 导入Feeds
    • 从网页上获得Feed
    • RSS Feed的使用
    • Atom Feed的使用
    • 单个Atom条目的处理
    • 修改Feed和条目结构
    • 自定义Feed和条目类
    • Zend_Feed_Reader
    • Zend_Feed_Writer
    • Zend_Feed_Pubsubhubbub
  • Zend_File
    • Zend_File_Transfer
    • Validators for Zend_File_Transfer
    • Filters for Zend_File_Transfer
  • Zend_Filter
    • 简介
    • 标准过滤器类
    • 过滤器链
    • 编写过滤器
    • Zend_Filter_Input
    • Zend_Filter_Inflector
  • Zend_Form
    • Zend_Form
    • Zend_Form 快速起步
    • 使用 Zend_Form_Element 生成表单元素
    • 使用 Zend_Form 生成表单
    • 使用 Zend_Form_Decorator 生成定制的表单标识（Markup）
    • Zend Framework 带有的标准表单元素
    • Zend Framework 带有的标准表单装饰器（Decorators）
    • Zend_Form 的国际化
    • Zend_Form 的高级用法
  • Zend_Gdata
    • Introduction
    • Authenticating with AuthSub
    • Using the Book Search Data API
    • Authenticating with ClientLogin
    • Using Google Calendar
    • Using Google Documents List Data API
    • Using Google Health
    • Using Google Spreadsheets
    • Using Google Apps Provisioning
    • Using Google Base
    • Using Picasa Web Albums
    • Using the YouTube Data API
    • Catching Gdata Exceptions
  • Zend_Http
    • Zend_Http_Client - 介绍
    • Zend_Http_Client - Advanced Usage
    • Zend_Http_Client - Connection Adapters
    • Zend_Http_Cookie and Zend_Http_CookieJar
    • Zend_Http_Response
  • Zend_InfoCard
    • Introduction
  • Zend_Json
    • 简介
    • 基本用法
    • JSON 对象
    • XML 到 JSON 转换
    • Zend_Json_Server - JSON-RPC server
  • Zend_Layout
    • 简介
    • Zend_Layout 快速入门
    • Zend_Layout 配置选项
    • Zend_Layout 高级用法
  • Zend_Ldap
    • Introduction
    • API overview
    • Usage Scenarios
    • Tools
    • Object oriented access to the LDAP tree using Zend_Ldap_Node
    • Getting information from the LDAP server
    • Serializing LDAP data to and from LDIF
  • Zend_Loader
    • 动态加载文件和类
    • The Autoloader
    • Resource Autoloaders
    • 加载插件
  • Zend_Locale
    • Introduction
    • Using Zend_Locale
    • Normalization and Localization
    • Working with Dates and Times
    • Supported locales
  • Zend_Log
    • 概述
    • Writers
    • Formatters
    • 过滤器
    • Using the Factory to Create a Log
  • Zend_Mail
    • 简介
    • 通过SMTP发送邮件
    • 通过一个SMTP连接发送多个邮
    • 使用不同的Transport对象
    • HTML邮件
    • 附件
    • 增加收件人
    • 控制MIME分界线
    • 外加邮件头信息
    • 字符集
    • 编码
    • SMTP 身份验证
    • Securing SMTP Transport
    • Reading Mail Messages
  • Zend_Markup
    • Introduction
    • Getting Started With Zend_Markup
    • Zend_Markup Parsers
    • Zend_Markup Renderers
  • Zend_Measure
    • Introduction
    • Creation of Measurements
    • Outputting measurements
    • Manipulating Measurements
    • Types of measurements
  • Zend_Memory
    • 概述
    • 内存管理器
    • 内存对象
  • Zend_Mime
    • Zend_Mime
    • Zend_Mime_Message
    • Zend_Mime_Part
  • Zend_Navigation
    • Introduction
    • Pages
    • Containers
  • Zend_Oauth
    • Introduction to OAuth
  • Zend_OpenId
    • Introduction
    • Zend_OpenId_Consumer Basics
    • Zend_OpenId_Provider
  • Zend_Paginator
    • Introduction
    • Usage
    • Configuration
    • Advanced usage
  • Zend_Pdf
    • 简介
    • 生成和加载 PDF 文档
    • 保存修改到 PDF 文档
    • 文档页面
    • Drawing
    • Interactive Features
    • Document Info and Metadata
    • Zend_Pdf module usage example
  • Zend_ProgressBar
    • Zend_ProgressBar
  • Zend_Queue
    • Introduction
    • Example usage
    • Framework
    • Adapters
    • Customizing Zend_Queue
    • Stomp
  • Zend_Reflection
    • Introduction
    • Zend_Reflection Examples
    • Zend_Reflection Reference
  • Zend_Registry
    • 使用对象注册表（Registry）
  • Zend_Rest
    • Introduction
    • Zend_Rest_Client
    • Zend_Rest_Server
  • Zend_Search_Lucene
    • 概述
    • 建立索引
    • 搜索索引
    • Query Language
    • 查询类型
    • 字符集
    • 扩展性
    • 与 Java Lucene 的互操作性
    • Advanced
    • Best Practices
  • Zend_Serializer
    • Introduction
    • Zend_Serializer_Adapter
  • Zend_Server
    • 简介
    • Zend_Server_Reflection
  • Zend_Service
    • 简介
    • Zend_Service_Akismet
    • Zend_Service_Amazon
    • Zend_Service_Amazon_Ec2
    • Zend_Service_Amazon_Ec2: Instances
    • Zend_Service_Amazon_Ec2: Windows Instances
    • Zend_Service_Amazon_Ec2: Reserved Instances
    • Zend_Service_Amazon_Ec2: CloudWatch Monitoring
    • Zend_Service_Amazon_Ec2: Amazon Machine Images (AMI)
    • Zend_Service_Amazon_Ec2: Elastic Block Stroage (EBS)
    • Zend_Service_Amazon_Ec2: Elastic IP Addresses
    • Zend_Service_Amazon_Ec2: Keypairs
    • Zend_Service_Amazon_Ec2: Regions and Availability Zones
    • Zend_Service_Amazon_Ec2: Security Groups
    • Zend_Service_Amazon_S3
    • Zend_Service_Amazon_Sqs
    • Zend_Service_Audioscrobbler
    • Zend_Service_Delicious
    • Zend_Service_DeveloperGarden
    • Zend_Service_Flickr
    • Zend_Service_LiveDocx
    • Zend_Service_Nirvanix
    • Zend_Service_ReCaptcha
    • Zend_Service_Simpy
    • Introduction
    • Zend_Service_StrikeIron
    • Zend_Service_StrikeIron: Bundled Services
    • Zend_Service_StrikeIron: Advanced Uses
    • Zend_Service_Technorati
    • Zend_Service_Twitter
    • Zend_Service_WindowsAzure
    • Zend_Service_Yahoo
  • Zend_Session
    • 简介
    • 基本用法
    • 高级用法
    • 全局会话管理
    • Zend_Session_SaveHandler_DbTable
  • Zend_Soap
    • Zend_Soap_Server
    • Zend_Soap_Client
    • WSDL Accessor
    • AutoDiscovery
  • Zend_Tag
    • Introduction
    • Zend_Tag_Cloud
  • Zend_Test
    • 简介
    • Zend_Test_PHPUnit
    • Zend_Test_PHPUnit_Db
  • Zend_Text
    • Zend_Text_Figlet
    • Zend_Text_Table
  • Zend_TimeSync
    • Introduction
    • Working with Zend_TimeSync
  • Zend_Tool
    • Using Zend_Tool On The Command Line
    • Extending Zend_Tool
  • Zend_Tool_Framework
    • Introduction
    • Using the CLI Tool
    • Architecture
    • Creating Providers to use with Zend_Tool_Framework
    • Shipped System Providers
    • Extending and Configuring Zend_Tool_Framework
  • Zend_Tool_Project
    • Introduction
    • Create A Project
    • Zend Tool Project Providers
    • Zend_Tool_Project 内部机制
  • Zend_Translate
    • 简介
    • Zend_Translate适配器
    • Using Translation Adapters
    • Creating source files
    • Additional features for translation
    • Plural notations for Translation
  • Zend_Uri
    • Zend_Uri
  • Zend_Validate
    • 简介
    • 标准校验类
    • 校验器链
    • 编写校验器
    • Validation Messages
  • Zend_Version
    • 读取Zend Framework的当前版本
  • Zend_View
    • 简介
    • 控制器脚本
    • 视图脚本
    • 视图助手（View Helper）
    • Zend_View_Abstract
  • Zend_Wildfire
    • Zend_Wildfire
  • Zend_XmlRpc
    • Introduction
    • Zend_XmlRpc_Client
    • Zend_XmlRpc_Server
  • ZendX_Console_Process_Unix
    • ZendX_Console_Process_Unix
  • ZendX_JQuery
    • Introduction
    • ZendX_JQuery View Helpers
    • ZendX_JQuery Form Elements and Decorators
Putting it all Together
Zend Framework手册 中文版
Zend Framework手册 中文版
Zend_Acl
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework简介
  • Learning Zend Framework
  • Zend Framework Reference
  • 系统需求
  • Zend Framework Migration Notes
  • Zend Framework 的 PHP 编码标准
  • Zend Framework Documentation Standard
  • Recommended Project Structure for Zend Framework MVC Applications
  • Zend Framework Performance Guide
  • 版权信息


Zend_Acl - Zend Framework Manual

Zend Framework Reference
Zend Framework Reference
Zend Framework手册 中文版
简介

Zend_Acl

Table of Contents
  • 简介
  • 精细的访问控制
  • 高级用法
Zend Framework Reference
Zend Framework Reference
Zend Framework手册 中文版
简介
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


简介 - Zend Framework Manual

Zend_Acl
Zend_Acl
Zend Framework手册 中文版
精细的访问控制

简介

Zend_Acl 为权限管理提供轻量并灵活的访问控制列表 (ACL,access control list) 的实现。一般地，应用软件可以利用这样的功能限制某些特定对象来访问特定保护的对象。

在本文档中，

  • resource （资源）是一个限制访问的对象。

  • role （角色）是一个可以发出请求去访问Resource的对象。

简单地说就是：roles 请求访问 resources。例如，如果停车服务员要进入汽车，那么，这个停车服务员就是发出请求的 role，而这辆汽车就是 resource，因为不是所有人都有权进入汽车。

通过规范和访问控制列表（ACL）的使用，应用软件可以控制角色（roles）如何来访问资源（resources）。

关于资源(Resource)

在 Zend_Acl 中，创建一个 resource 非常简单。Zend_Acl 提供了 resource 接口Zend_Acl_Resource_Interface 使开发者在程序中创建 resources 非常容易。 为了使Zend_Acl把某个对象当作一个resource，一个类只需要实现这个只包含了一个方法 getResourceId() 的接口。 另外，Zend_Acl_Resource是一个包含在 Zend_Acl 里作为一个基本的 resource 实现的类，开发者可以任意扩展它。

Zend_Acl 提供了一个树结构，它可以添加多个 resources (或者叫“访问控制下的区域”）。因为 resources 被存储在这样一个树结构， 所以它们可以被组织成从一般（树根）到特殊（树叶）。基于特殊resource的查询将自动从resource的等级结构中搜索分配给祖先rResources的规则， 它允许简单的规则继承。例如，要把一个缺省的规则应用到一个城市的每个建筑物，就简单地把这个规则分配给这个城市， 而不是把规则分配给每个建筑物。然而，有些建筑物也许要求例外的规则，在Zend_Acl里，很容易地通过分配例外规则给每个有这样要求的建筑物来实现。 一个 resource 可以从唯一的一个父 resource 继承，而这个父 resource 也有它自己的父 resource，等等。

Zend_Acl 也支持基于 resources 的权限（例如："create", "read", "update", "delete"）， 所以开发者可以根据 resource 分配影响全部或者特殊权限的规则到一个或多个资源。

关于角色(Role)

象 Resources 一样，创建一个 role 也非常简单。 Zend_Acl 提供了 Zend_Acl_Role_Interface 使开发者创建 roles 非常容易。 为了使Zend_Acl把某个对象当作一个 role，一个类只需要实现这个只包含了一个方法 getRoleId() 的接口。 另外，Zend_Acl_Role是一个包含在Zend_Acl里作为一个基本的 role 实现的类，开发者可以任意扩展它。

在 Zend_Acl, 一个 role 可以从一个或多个 role 继承，这就是在 role 中支持规则的继承。例如，一个用户 role，如 “sally”， 可以属于一个或多个 role，如：“editor”和“administrator”。开发者可以分别给“editor”和“administrator”分配规则， 而“sally”将从它们俩继承规则，不需要直接给“sally”分配规则。

虽然从多重角色继承的能力非常有用，但是多重继承也带来了一定程度的复杂性。下面的例子来示例含糊情形和Zend_Acl如何解决它。

Example #1 角色之间的多重继承

下面的代码定义了三个基本角色 - "guest", "member", 和 "admin" - 其它角色可以从它们继承。接着，创建一个"someUser" 角色并从其它三个基本角色继承。 在$parents 数组里这些角色出现的顺序很重要。 必要时，Zend_Acl 不但搜索为被查询的角色 （这里指 "someUser"）定义的访问规则，而且搜索为被查询的角色所继承的角色 （这里指 "guest", "member", and "admin"）定义的访问规则：

$acl = new Zend_Acl();

$acl->addRole(new Zend_Acl_Role('guest'))
    ->addRole(new Zend_Acl_Role('member'))
    ->addRole(new Zend_Acl_Role('admin'));

$parents = array('guest', 'member', 'admin');
$acl->addRole(new Zend_Acl_Role('someUser'), $parents);

$acl->add(new Zend_Acl_Resource('someResource'));

$acl->deny('guest', 'someResource');
$acl->allow('member', 'someResource');

echo $acl->isAllowed('someUser', 'someResource') ? 'allowed' : 'denied';

因为没有明确地为 "someUser"和"someResource" 定义规则， 所以Zend_Acl 必须搜索可能为"someUser"所继承的角色定义的规则。 首先，"admin"角色被访问，没有给它定义访问规则。 接着，"member"角色被访问，Zend_Acl发现有个规则允许"member" 访问"someResource"。

如果Zend_Acl打算继续检查为父角色所定义的规则，然而， 它将发现"guest" 被拒绝访问"someResource" 。 这带来了模棱两可的情形， "someUser"即被允许又被禁止访问"someResource"，因为它从不同的父角色继承了冲突的规则。

Zend_Acl 解决了这个模棱两可的问题，当它发现第一个可用的规则时，就完成了查询。 对于这个案例，因为"member"角色先于"guest" 角色被检查，这个例子将打印"allowed"。

Note: 当为一个角色指定多重父（角色）时，请记住，对于一个授权查询的可用规则，最后列出的父（角色）是首先被搜索的。

创建访问控制列表(ACL)

ACL 可以表示任何一组物理或虚拟对象，然而，作为示范，我们将创建一个基本的内容管理系统的（CMS）ACL， 在一个范围很宽的多样化区域里，它将维护若干个等级的组。为创建一个新的 ACL 对象，我们不带参数地实例化这个 ACL：

$acl = new Zend_Acl();

Note: 除非开发者指明一个"allow" 规则，Zend_Acl 禁止任何 role 对任何 resource 的任何访问权限。

注册角色(Role)

CMS 通常需要一个分级的权限系统来决定它的用户的授权能力。 作为示范，“Guest”组允许有限的访问，“Staff”适合大多数的执行日常操作的CMS用户，“Editor”组适合于发布、复核、存档和删除内容， 最后“Administrator”组的任务包括所有其它组的内容并包括敏感的信息、用户管理、后台配置数据和备份/导出。 这组许可可以被表示为一个 role 注册表，允许每个组从“”组继承权限，也可以为单一的组提供独特的权限。这些许可可以表示如下：

一个CMS范例的访问控制
名称 | 独特的许可 | 从...继承的许可
Guest | View | N/A
Staff | Edit, Submit, Revise | Guest
Editor | Publish, Archive, Delete | Staff
Administrator | (Granted all access) | N/A

对于这个范例，Zend_Acl_Role 被使用，但任何实现 Zend_Acl_Role_Interface 的对象是可接受的。这些组可以被添加到 role 注册表如下：

$acl = new Zend_Acl();

// 用 Zend_Acl_Role 把组添加到 Role 注册表
// Guest 不继承访问控制
$roleGuest = new Zend_Acl_Role('guest');
$acl->addRole($roleGuest);

// Staff 从 guest 继承
$acl->addRole(new Zend_Acl_Role('staff'), $roleGuest);

/*
另外, 上面的也可这样来写：
$acl->addRole(new Zend_Acl_Role('staff'), 'guest');
*/

// Editor 从 staff 继承
$acl->addRole(new Zend_Acl_Role('editor'), 'staff');

// Administrator 不继承访问控制
$acl->addRole(new Zend_Acl_Role('administrator'));

定义访问控制

现在 ACL 包含了相关的 roles，可以建立规则来定义 roles 如何访问 resources。 你也许注意到我们在这个范例里没有定义任何特定的 resources， 这简单地表示这些规则适用于所有 resources。 Zend_Acl 提供一个实现，籍此，规则只需要被分配从一般到特殊，最小化规则的需求，因为 resources 和 roles 继承由它们祖先定义的规则。

Note: 一般来说，当且仅当更具体的规则没有使用， Zend_Acl 就服从已给定的规则。

因此，我们可以用最少量的代码来定义适度复杂的规则。应用上面定义的基本许可：

$acl = new Zend_Acl();

$roleGuest = new Zend_Acl_Role('guest');
$acl->addRole($roleGuest);
$acl->addRole(new Zend_Acl_Role('staff'), $roleGuest);
$acl->addRole(new Zend_Acl_Role('editor'), 'staff');
$acl->addRole(new Zend_Acl_Role('administrator'));

// Guest 只可以浏览内容
$acl->allow($roleGuest, null, 'view');

/*
另外, 上面也可写为：
$acl->allow('guest', null, 'view');
*/

// Staff 从 guest 继承浏览权限，但也要另外的权限
$acl->allow('staff', null, array('edit', 'submit', 'revise'));

// Editor 从 Staff 继承 view, edit, submit 和 revise 权限
// 但也要另外的权限
$acl->allow('editor', null, array('publish', 'archive', 'delete'));

// Administrator 不需要继承任何权限，它拥有所有的权限
$acl->allow('administrator');

在上面 allow() 中调用中 null 的值用来表明 allow 规则适用于所有的 resources。

查询 ACL

我们现在有一个灵活的 ACL 可以用来决定请求者在整个 web 应用里是否拥有执行功能的许可。用isAllowed()方法来执行查询相当简单：

echo $acl->isAllowed('guest', null, 'view') ?
     "allowed" : "denied";
// allowed

echo $acl->isAllowed('staff', null, 'publish') ?
     "allowed" : "denied";
// denied

echo $acl->isAllowed('staff', null, 'revise') ?
     "allowed" : "denied";
// allowed

echo $acl->isAllowed('editor', null, 'view') ?
     "allowed" : "denied";
// allowed because of inheritance from guest

echo $acl->isAllowed('editor', null, 'update') ?
     "allowed" : "denied";
// denied because no allow rule for 'update'

echo $acl->isAllowed('administrator', null, 'view') ?
     "allowed" : "denied";
// allowed because administrator is allowed all privileges

echo $acl->isAllowed('administrator') ?
     "allowed" : "denied";
// allowed because administrator is allowed all privileges

echo $acl->isAllowed('administrator', null, 'update') ?
     "allowed" : "denied";
// allowed because administrator is allowed all privileges
Zend_Acl
Zend_Acl
Zend Framework手册 中文版
精细的访问控制
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • 简介
  • 精细的访问控制
  • 高级用法


高级用法 - Zend Framework Manual

精细的访问控制
Zend_Acl
Zend Framework手册 中文版
Zend_Amf

高级用法

保存 ACL 数据确保持久性

Zend_Acl 就是这样设计的，它不需要为 ACL 数据的存储而要求任何特别的后台技术如数据库或者缓冲服务器。它的完全的 PHP 实现使得在Zend_Acl之上构建定制的管理工具相当地容易和灵活。许多情形需要一些 ACL 的交互式维护，并且 Zend_Acl 为设定、查询、应用软件的访问控制提供了方法。

因为期望应用案例有多种变化来适应不同的情形，ACL 数据的存储因此留给开发者来完成。因为 Zend_Acl 是可序列化的，所以 ACL 的对象可以用 PHP 中的 » serialize() 函数来序列化，并且结果可以存在开发者所期望的任何地方，例如文件、数据库、或缓存机构。

使用声明(Assert)来编写条件性的 ACL 规则

有时候允许或禁止一个 Role 访问一个 Resource 的规则不是绝对的而是依靠不同的标准。例如，只有在 8：00am 和 5:00pm 之间，特定的访问才被允许。另外一个禁止访问的例子是因为一个请求来自于被标记为不良的 IP 地址。Zend_Acl 对基于无论开发者有什么需要的条件的规则实现有个内置的支持。

Zend_Acl 用 Zend_Acl_Assert_Interface 提供支持有条件的规则。为了使用规则声明接口，开发者写了一个实现接口中 assert() 方法的类。

class CleanIPAssertion implements Zend_Acl_Assert_Interface
{
    public function assert(Zend_Acl $acl,
                           Zend_Acl_Role_Interface $role = null,
                           Zend_Acl_Resource_Interface $resource = null,
                           $privilege = null)
    {
        return $this->_isCleanIP($_SERVER['REMOTE_ADDR']);
    }

    protected function _isCleanIP($ip)
    {
        // ...
    }
}}

一旦声明类可用，当分配有条件的规则时，开发者必需提供声明类的一个实例。用声明建立的规则只适用于当声明方法返回 true。

$acl = new Zend_Acl();
$acl->allow(null, null, null, new CleanIPAssertion());

上面的代码创建了一个有条件的 allow 规则，它允许所有人对所有资源有所有的访问权限，除非请求的 IP 列在“黑名单”上。如果一个请求来自于一个不是“清白”的 IP, 这个 allow 规则就不适用。因此这个规则适用于所有的 Roles、所有的 Resources 和所有的权限，一个“不清白”的 IP 将导致一个禁止访问。这是一个特例，对于其它所有案例（例如，一个特定的 Role、Resource、或者被指定规则的权限），一个失败的声明将导致规则不适用，并且其它规则将被用于决定访问是被允许或禁止。

为了给声明类提供一个上下文环境(Context)来决定所需的条件，Assert对象的 assert() 方法将以ACL、 Role、 Resource 和适用于授权查询（例如isAllowed()）的权限作为参数。

精细的访问控制
Zend_Acl
Zend Framework手册 中文版
Zend_Amf
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • 简介
  • 精细的访问控制
  • 高级用法


精细的访问控制 - Zend Framework Manual

简介
Zend_Acl
Zend Framework手册 中文版
高级用法

精细的访问控制

精细的访问控制

在前一章节中定义的基本的 ACL 显示如何在整个 ACL (所有的 resources )允许各种各样的权限。然而在实践中，访问控制趋向于拥有例外和可变程度的复杂性。Zend_Acl 允许你直截了当并灵活地完成这些精细准确的控制。

对于CMS范例，'staff' 组覆盖了绝大多数用户的需求，同时，一个新的 'marketing' 组要求在CMS中访问时事通讯和最近的新闻。这个组相当地自给自足并有能力发布和归档时事通讯和最近的新闻。

另外，还要求 'staff' 组被允许浏览新闻故事但不能修订最近的新闻。最后，不可能让每一个人（包括系统管理员）去归档任何'announcement' 新闻故事，因为它们只有1-2天的生命周期。

首先我们修订 role 注册表来反映这些变化。我们已经确定 'marketing' 组和 'staff' 组有着同样的基本许可，所以我们用从 'staff' 组继承许可的方法来定义 'marketing' 组

// 新 marketing 组从 staff 组继承许可
$acl->addRole(new Zend_Acl_Role('marketing'), 'staff');

然后， 注意上面的访问控制涉及到特定的 resources ( 例如 "newsletter", "latest news", "announcement news"). 现在我们来添加这些 resources：

// Create Resources for the rules

// newsletter
$acl->add(new Zend_Acl_Resource('newsletter'));

// news
$acl->add(new Zend_Acl_Resource('news'));

// latest news
$acl->add(new Zend_Acl_Resource('latest'), 'news');

// announcement news
$acl->add(new Zend_Acl_Resource('announcement'), 'news');

接着，这个是在 ACL 的目标区域定义更特定的规则的概况：

// Marketing must be able to publish and archive newsletters and the
// latest news
$acl->allow('marketing',
            array('newsletter', 'latest'),
            array('publish', 'archive'));

// Staff (和 marketing, 通过继承), 禁止修订 latest news
$acl->deny('staff', 'latest', 'revise');

// Everyone (包括 administrators) 禁止归档 news announcements
$acl->deny(null, 'announcement', 'archive');

我们现在能够查询到 ACL 的最新变化：

echo $acl->isAllowed('staff', 'newsletter', 'publish') ?
     "allowed" : "denied";
// denied

echo $acl->isAllowed('marketing', 'newsletter', 'publish') ?
     "allowed" : "denied";
// allowed

echo $acl->isAllowed('staff', 'latest', 'publish') ?
     "allowed" : "denied";
// denied

echo $acl->isAllowed('marketing', 'latest', 'publish') ?
     "allowed" : "denied";
// allowed

echo $acl->isAllowed('marketing', 'latest', 'archive') ?
     "allowed" : "denied";
// allowed

echo $acl->isAllowed('marketing', 'latest', 'revise') ?
     "allowed" : "denied";
// denied

echo $acl->isAllowed('editor', 'announcement', 'archive') ?
     "allowed" : "denied";
// denied

echo $acl->isAllowed('administrator', 'announcement', 'archive') ?
     "allowed" : "denied";
// denied

除去访问控制

要从 ACL 中除去一个或多个访问规则，只要简单地用 removeAllow() 或 removeDeny() 方法即可。如果提供一个null参数值给 allow() 和 deny() 方法，则访问规则将应用到所有的角色，资源和/或权限上。

// 除去 “禁止 staff 修订最近的新闻”(和marketing, 由于继承的原因)
//（等于允许staff修订最近的新闻 Jason注）
$acl->removeDeny('staff', 'latest', 'revise');

echo $acl->isAllowed('marketing', 'latest', 'revise') ?
     "allowed" : "denied";
// allowed

// Remove the allowance of publishing and archiving newsletters to
// marketing
$acl->removeAllow('marketing',
                  'newsletter',
                  array('publish', 'archive'));

echo $acl->isAllowed('marketing', 'newsletter', 'publish') ?
     "allowed" : "denied";
// denied

echo $acl->isAllowed('marketing', 'newsletter', 'archive') ?
     "allowed" : "denied";
// denied

如上所示，对于权限的修改可能是增量的，但使用 null 值（未指定权限项的参数值）超越了对权限的增量修改。（所谓的增量修改是指可以对 Resources 一个一个地添加权限或禁止，而如果未指定权限参数值，即使用 null 值，可以使得这些步骤简化，一次性地对某个Resource的所有权限进行允许或禁止。Jason注，Haohappy补）

// 允许 marketing 对 latest news 有所有的许可
$acl->allow('marketing', 'latest');

echo $acl->isAllowed('marketing', 'latest', 'publish') ?
     "allowed" : "denied";
// allowed

echo $acl->isAllowed('marketing', 'latest', 'archive') ?
     "allowed" : "denied";
// allowed

echo $acl->isAllowed('marketing', 'latest', 'anything') ?
     "allowed" : "denied";
// allowed
简介
Zend_Acl
Zend Framework手册 中文版
高级用法
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • 简介
  • 精细的访问控制
  • 高级用法


Zend_Amf - Zend Framework Manual

高级用法
Zend Framework Reference
Zend Framework手册 中文版
Introduction

Zend_Amf

Table of Contents
  • Introduction
  • Zend_Amf_Server
高级用法
Zend Framework Reference
Zend Framework手册 中文版
Introduction
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


Introduction - Zend Framework Manual

Zend_Amf
Zend_Amf
Zend Framework手册 中文版
Zend_Amf_Server

Introduction

Zend_Amf provides support for Adobe's » Action Message Format (AMF), to allow communication between Adobe's » Flash Player and PHP. Specifically, it provides a gateway server implementation for handling requests sent from the Flash Player to the server and mapping these requests to object and class methods and arbitrary callbacks.

The » AMF3 specification is freely available, and serves as a reference for what types of messages may be sent between the Flash Player and server.

Zend_Amf
Zend_Amf
Zend Framework手册 中文版
Zend_Amf_Server
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Amf
  • Introduction
  • Zend_Amf_Server


Zend_Amf_Server - Zend Framework Manual

Introduction
Zend_Amf
Zend Framework手册 中文版
Zend_Application

Zend_Amf_Server

Zend_Amf_Server provides an RPC-style server for handling requests made from the Adobe Flash Player using the AMF protocol. Like all Zend Framework server classes, it follows the SoapServer API, providing an easy to remember interface for creating servers.

Example #1 Basic AMF Server

Let's assume that you have created a class Foo with a variety of public methods. You may create an AMF server using the following code:

  1. $server = new Zend_Amf_Server();
  2. $server->setClass('Foo');
  3. $response = $server->handle();
  4. echo $response;

Alternately, you may choose to attach a simple function as a callback instead:

  1. $server = new Zend_Amf_Server();
  2. $server->addFunction('myUberCoolFunction');
  3. $response = $server->handle();
  4. echo $response;

You could also mix and match multiple classes and functions. When doing so, we suggest namespacing each to ensure that no method name collisions occur; this can be done by simply passing a second string argument to either addFunction() or setClass():

  1. $server = new Zend_Amf_Server();
  2. $server->addFunction('myUberCoolFunction', 'my')
  3.        ->setClass('Foo', 'foo')
  4.        ->setClass('Bar', 'bar');
  5. $response = $server->handle();
  6. echo $response;

The Zend_Amf_Server also allows services to be dynamically loaded based on a supplied directory path. You may add as many directories as you wish to the server. The order that you add the directories to the server will be the order that the LIFO search will be performed on the directories to match the class. Adding directories is completed with the addDirectory() method.

  1. $server->addDirectory(dirname(__FILE__) .'/../services/');
  2. $server->addDirectory(dirname(__FILE__) .'/../package/');

When calling remote services your source name can have underscore ("_") and dot (".") directory delimiters. When an underscore is used PEAR and Zend Framework class naming conventions will be respected. This means that if you call the service com_Foo_Bar the server will look for the file Bar.php in the each of the included paths at com/Foo/Bar.php. If the dot notation is used for your remote service such as com.Foo.Bar each included path will have com/Foo/Bar.php append to the end to autoload Bar.php

All AMF requests sent to the script will then be handled by the server, and an AMF response will be returned.

Note: All Attached Methods and Functions Need Docblocks
 Like all other server components in Zend Framework, you must document your class methods using PHP docblocks. At the minimum, you need to provide annotations for each required argument as well as the return value. As examples:

  1. // Function to attach:
  2.
  3. /**
  4. * @param  string $name
  5. * @param  string $greeting
  6. * @return string
  7. */
  8. function helloWorld($name, $greeting = 'Hello')
  9. {
  10.     return $greeting . ', ' . $name;
  11. }
  1. // Attached class
  2.
  3. class World
  4. {
  5.     /**
  6.      * @param  string $name
  7.      * @param  string $greeting
  8.      * @return string
  9.      */
  10.     public function hello($name, $greeting = 'Hello')
  11.     {
  12.         return $greeting . ', ' . $name;
  13.     }
  14. }
Other annotations may be used, but will be ignored.

Connecting to the Server from Flex

Connecting to your Zend_Amf_Server from your Flex project is quite simple; you simply need to point your endpoint URI to your Zend_Amf_Server script.

Say, for instance, you have created your server and placed it in the server.php file in your application root, and thus the URI is http://example.com/server.php. In this case, you would modify your services-config.xml file to set the channel endpoint uri attribute to this value.

If you have never created a service-config.xml file you can do so by opening your project in your Navigator window. Right click on the project name and select 'properties'. In the Project properties dialog go into 'Flex Build Path' menu, 'Library path' tab and be sure the 'rpc.swc' file is added to your projects path and Press Ok to close the window.

You will also need to tell the compiler to use the service-config.xml to find the RemoteObject endpoint. To do this open your project properties panel again by right clicking on the project folder from your Navigator and selecting properties. From the properties popup select 'Flex Compiler' and add the string: -services "services-config.xml". Press Apply then OK to return to update the option. What you have just done is told the Flex compiler to look to the services-config.xml file for runtime variables that will be used by the RemotingObject class.

We now need to tell Flex which services configuration file to use for connecting to our remote methods. For this reason create a new 'services-config.xml' file into your Flex project src folder. To do this right click on the project folder and select 'new' 'File' which will popup a new window. Select the project folder and then name the file 'services-config.xml' and press finish.

Flex has created the new services-config.xml and has it open. Use the following example text for your services-config.xml file. Make sure that you update your endpoint to match that of your testing server. Make sure you save the file.

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <services-config>
  3.     <services>
  4.         <service id="zend-service"
  5.             class="flex.messaging.services.RemotingService"
  6.             messageTypes="flex.messaging.messages.RemotingMessage">
  7.             <destination id="zend">
  8.                 <channels>
  9.                     <channel ref="zend-endpoint"/>
  10.                 </channels>
  11.                 <properties>
  12.                     <source>*</source>
  13.                 </properties>
  14.             </destination>
  15.         </service>
  16.     </services>
  17.     <channels>
  18.         <channel-definition id="zend-endpoint"
  19.             class="mx.messaging.channels.AMFChannel">
  20.             <endpoint uri="http://example.com/server.php"
  21.                 class="flex.messaging.endpoints.AMFEndpoint"/>
  22.         </channel-definition>
  23.     </channels>
  24. </services-config>

There are two key points in the example. First, but last in the listing, we create an AMF channel, and specify the endpoint as the URL to our Zend_Amf_Server:

  1. <channel-definition id="zend-endpoint"
  2.     <endpoint uri="http://example.com/server.php"
  3.         class="flex.messaging.endpoints.AMFEndpoint"/>
  4. </channel-definition>

Notice that we've given this channel an identifier, "zend-endpoint". The example create a service destination that refers to this channel, assigning it an ID as well -- in this case "zend".

Within our Flex MXML files, we need to bind a RemoteObject to the service. In MXML, this might be done as follows:

  1. <mx:RemoteObject id="myservice"
  2.     fault="faultHandler(event)"
  3.     showBusyCursor="true"
  4.     destination="zend">

Here, we've defined a new remote object identified by "myservice" bound to the service destination "zend" we defined in the services-config.xml file. We then call methods on it in our ActionScript by simply calling "myservice.<method>". As an example:

  1. myservice.hello("Wade");

When namespacing, you would use "myservice.<namespace>.<method>":

  1. myservice.world.hello("Wade");

For more information on Flex RemoteObject invocation, » visit the Adobe Flex 3 Help site.

Error Handling

By default, all exceptions thrown in your attached classes or functions will be caught and returned as AMF ErrorMessages. However, the content of these ErrorMessage objects will vary based on whether or not the server is in "production" mode (the default state).

When in production mode, only the exception code will be returned. If you disable production mode -- something that should be done for testing only -- most exception details will be returned: the exception message, line, and backtrace will all be attached.

To disable production mode, do the following:

  1. $server->setProduction(false);

To re-enable it, pass a TRUE boolean value instead:

  1. $server->setProduction(true);

Note: Disable production mode sparingly!
 We recommend disabling production mode only when in development. Exception messages and backtraces can contain sensitive system information that you may not wish for outside parties to access. Even though AMF is a binary format, the specification is now open, meaning anybody can potentially deserialize the payload.

One area to be especially careful with is PHP errors themselves. When the display_errors INI directive is enabled, any PHP errors for the current error reporting level are rendered directly in the output -- potentially disrupting the AMF response payload. We suggest turning off the display_errors directive in production to prevent such problems

AMF Responses

Occasionally you may desire to manipulate the response object slightly, typically to return extra message headers. The handle() method of the server returns the response object, allowing you to do so.

Example #2 Adding Message Headers to the AMF Response

In this example, we add a 'foo' MessageHeader with the value 'bar' to the response prior to returning it.

  1. $response = $server->handle();
  2. $response->addAmfHeader(new Zend_Amf_Value_MessageHeader('foo', true, 'bar'))
  3. echo $response;

Typed Objects

Similar to SOAP, AMF allows passing objects between the client and server. This allows a great amount of flexibility and coherence between the two environments.

Zend_Amf provides three methods for mapping ActionScript and PHP objects.

  • First, you may create explicit bindings at the server level, using the setClassMap() method. The first argument is the ActionScript class name, the second the PHP class name it maps to:

    1. // Map the ActionScript class 'ContactVO' to the PHP class 'Contact':
    2. $server->setClassMap('ContactVO', 'Contact');

  • Second, you can set the public property $_explicitType in your PHP class, with the value representing the ActionScript class to map to:

    1. class Contact
    2. {
    3.     public $_explicitType = 'ContactVO';
    4. }

  • Third, in a similar vein, you may define the public method getASClassName() in your PHP class; this method should return the appropriate ActionScript class:

    1. class Contact
    2. {
    3.     public function getASClassName()
    4.     {
    5.         return 'ContactVO';
    6.     }
    7. }

Although we have created the ContactVO on the server we now need to make its corresponding class in AS3 for the server object to be mapped to.

Right click on the src folder of the Flex project and select New -> ActionScript File. Name the file ContactVO and press finish to see the new file. Copy the following code into the file to finish creating the class.

  1. package
  2. {
  3.     [Bindable]
  4.     [RemoteClass(alias="ContactVO")]
  5.     public class ContactVO
  6.     {
  7.         public var id:int;
  8.         public var firstname:String;
  9.         public var lastname:String;
  10.         public var email:String;
  11.         public var mobile:String;
  12.         public function ProductVO():void {
  13.         }
  14.     }
  15. }

The class is syntactically equivalent to the PHP of the same name. The variable names are exactly the same and need to be in the same case to work properly. There are two unique AS3 meta tags in this class. The first is bindable which makes fire a change event when it is updated. The second tag is the RemoteClass tag which defines that this class can have a remote object mapped with the alias name in this case ContactVO. It is mandatory that this tag the value that was set is the PHP class are strictly equivalent.

  1. [Bindable]
  2. private var myContact:ContactVO;
  3.
  4. private function getContactHandler(event:ResultEvent):void {
  5.     myContact = ContactVO(event.result);
  6. }

The following result event from the service call is cast instantly onto the Flex ContactVO. Anything that is bound to myContact will be updated with the returned ContactVO data.

Resources

Zend_Amf provides tools for mapping resource types returned by service classes into data consumable by ActionScript.

In order to handle specific resource type, the user needs to create a plugin class named after the resource name, with words capitalized and spaces removed (so, resource type "mysql result" becomes MysqlResult), with some prefix, e.g. My_MysqlResult. This class should implement one method, parse(), receiving one argument - the resource - and returning the value that should be sent to ActionScript. The class should be located in the file named after the last component of the name, e.g. MysqlResult.php.

The directory containing the resource handling plugins should be registered with Zend_Amf type loader:

  1. Zend_Amf_Parse_TypeLoader::addResourceDirectory(
  2.     "My",
  3.     "application/library/resources/My"
  4. );

For detailed discussion of loading plugins, please see the plugin loader section.

Default directory for Zend_Amf resources is registered automatically and currently contains handlers for "mysql result" and "stream" resources.

  1. // Example class implementing handling resources of type mysql result
  2. class Zend_Amf_Parse_Resource_MysqlResult
  3. {
  4.     /**
  5.      * Parse resource into array
  6.      *
  7.      * @param resource $resource
  8.      * @return array
  9.      */
  10.     public function parse($resource) {
  11.         $result = array();
  12.         while($row = mysql_fetch_assoc($resource)) {
  13.             $result[] = $row;
  14.         }
  15.         return $result;
  16.     }
  17. }

Trying to return unknown resource type (i.e., one for which no handler plugin exists) will result in an exception.

Connecting to the Server from Flash

Connecting to your Zend_Amf_Server from your Flash project is slightly different than from Flex. However once the connection Flash functions with Zend_Amf_Server the same way is flex. The following example can also be used from a Flex AS3 file. We will reuse the same Zend_Amf_Server configuration along with the World class for our connection.

Open Flash CS and create and new Flash File (ActionScript 3). Name the document ZendExample.fla and save the document into a folder that you will use for this example. Create a new AS3 file in the same directory and call the file Main.as. Have both files open in your editor. We are now going to connect the two files via the document class. Select ZendExample and click on the stage. From the stage properties panel change the Document class to Main. This links the Main.as ActionScript file with the user interface in ZendExample.fla. When you run the Flash file ZendExample the Main.as class will now be run. Next we will add ActionScript to make the AMF call.

We now are going to make a Main class so that we can send the data to the server and display the result. Copy the following code into your Main.as file and then we will walk through the code to describe what each element's role is.

  1. package {
  2.   import flash.display.MovieClip;
  3.   import flash.events.*;
  4.   import flash.net.NetConnection;
  5.   import flash.net.Responder;
  6.
  7.   public class Main extends MovieClip {
  8.     private var gateway:String = "http://example.com/server.php";
  9.     private var connection:NetConnection;
  10.     private var responder:Responder;
  11.
  12.     public function Main() {
  13.       responder = new Responder(onResult, onFault);
  14.       connection = new NetConnection;
  15.       connection.connect(gateway);
  16.     }
  17.
  18.     public function onComplete( e:Event ):void{
  19.       var params = "Sent to Server";
  20.       connection.call("World.hello", responder, params);
  21.     }
  22.
  23.     private function onResult(result:Object):void {
  24.       // Display the returned data
  25.       trace(String(result));
  26.     }
  27.     private function onFault(fault:Object):void {
  28.       trace(String(fault.description));
  29.     }
  30.   }
  31. }

We first need to import two ActionScript libraries that perform the bulk of the work. The first is NetConnection which acts like a by directional pipe between the client and the server. The second is a Responder object which handles the return values from the server related to the success or failure of the call.

  1. import flash.net.NetConnection;
  2. import flash.net.Responder;

In the class we need three variables to represent the NetConnection, Responder, and the gateway URL to our Zend_Amf_Server installation.

  1. private var gateway:String = "http://example.com/server.php";
  2. private var connection:NetConnection;
  3. private var responder:Responder;

In the Main constructor we create a responder and a new connection to the Zend_Amf_Server endpoint. The responder defines two different methods for handling the response from the server. For simplicity I have called these onResult and onFault.

  1. responder = new Responder(onResult, onFault);
  2. connection = new NetConnection;
  3. connection.connect(gateway);

In the onComplete function which is run as soon as the construct has completed we send the data to the server. We need to add one more line that makes a call to the Zend_Amf_Server World->hello function.

  1. connection.call("World.hello", responder, params);

When we created the responder variable we defined an onResult and onFault function to handle the response from the server. We added this function for the successful result from the server. A successful event handler is run every time the connection is handled properly to the server.

  1. private function onResult(result:Object):void {
  2.     // Display the returned data
  3.     trace(String(result));
  4. }

The onFault function, is called if there was an invalid response from the server. This happens when there is an error on the server, the URL to the server is invalid, the remote service or method does not exist, and any other connection related issues.

  1. private function onFault(fault:Object):void {
  2.     trace(String(fault.description));
  3. }

Adding in the ActionScript to make the remoting connection is now complete. Running the ZendExample file now makes a connection to Zend Amf. In review you have added the required variables to open a connection to the remote server, defined what methods should be used when your application receives a response from the server, and finally displayed the returned data to output via trace().

Authentication

Zend_Amf_Server allows you to specify authentication and authorization hooks to control access to the services. It is using the infrastructure provided by Zend_Auth and Zend_Acl components.

In order to define authentication, the user provides authentication adapter extening Zend_Amf_Auth_Abstract abstract class. The adapter should implement the authenticate() method just like regular authentication adapter.

The adapter should use properties _username and _password from the parent Zend_Amf_Auth_Abstract class in order to authenticate. These values are set by the server using setCredentials() method before call to authenticate() if the credentials are received in the AMF request headers.

The identity returned by the adapter should be an object containing property role for the ACL access control to work.

If the authentication result is not successful, the request is not proceseed further and failure message is returned with the reasons for failure taken from the result.

The adapter is connected to the server using setAuth() method:

  1. $server->setAuth(new My_Amf_Auth());

Access control is performed by using Zend_Acl object set by setAcl() method:

  1. $acl = new Zend_Acl();
  2. createPermissions($acl); // create permission structure
  3. $server->setAcl($acl);

If the ACL object is set, and the class being called defines initAcl() method, this method will be called with the ACL object as an argument. The class then can create additional ACL rules and return TRUE, or return FALSE if no access control is required for this class.

After ACL have been set up, the server will check if access is allowed with role set by the authentication, resource being the class name (or NULL for function calls) and privilege being the function name. If no authentication was provided, then if the anonymous role was defined, it will be used, otherwise the access will be denied.

  1. if($this->_acl->isAllowed($role, $class, $function)) {
  2.     return true;
  3. } else {
  4.     require_once 'Zend/Amf/Server/Exception.php';
  5.     throw new Zend_Amf_Server_Exception("Access not allowed");
  6. }
Introduction
Zend_Amf
Zend Framework手册 中文版
Zend_Application
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Amf
  • Introduction
  • Zend_Amf_Server


Zend_Application - Zend Framework Manual

Zend_Amf_Server
Zend Framework Reference
Zend Framework手册 中文版
简介

Zend_Application

Table of Contents
  • 简介
  • Zend_Application Quick Start
  • Theory of Operation
  • Examples
  • Core Functionality
  • Available Resource Plugins
Zend_Amf_Server
Zend Framework Reference
Zend Framework手册 中文版
简介
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


简介 - Zend Framework Manual

Zend_Application
Zend_Application
Zend Framework手册 中文版
Zend_Application Quick Start

简介

Zend_Application 提供了一个可重用资源的引导，通用和模块化的引导类和依赖检查。 同时默认负责设置 PHP 环境变量和自动加载功能。

Zend_Application
Zend_Application
Zend Framework手册 中文版
Zend_Application Quick Start
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Application
  • 简介
  • Zend_Application Quick Start
  • Theory of Operation
  • Examples
  • Core Functionality
  • Available Resource Plugins


Zend_Application Quick Start - Zend Framework Manual

简介
Zend_Application
Zend Framework手册 中文版
Theory of Operation

Zend_Application Quick Start

There are two paths to getting started with Zend_Application, and they depend on how you start your project. In each case, you always start with creating a Bootstrap class, and a related configuration file.

If you plan on using Zend_Tool to create your project, continue reading below. If you will be adding Zend_Application to an existing project, you'll want to skip ahead.

Using Zend_Tool

The quickest way to start using Zend_Application is to use Zend_Tool to generate your project. This will also create your Bootstrap class and file.

To create a project, execute the zf command (on *nix systems):

  1. % zf create project newproject

Or the Windows zf.bat command:

  1. C:> zf.bat create project newproject

Both will create a project structure that looks like the following:

  1. newproject
  2. |-- application
  3. |   |-- Bootstrap.php
  4. |   |-- configs
  5. |   |   `-- application.ini
  6. |   |-- controllers
  7. |   |   |-- ErrorController.php
  8. |   |   `-- IndexController.php
  9. |   |-- models
  10. |   `-- views
  11. |       |-- helpers
  12. |       `-- scripts
  13. |           |-- error
  14. |           |   `-- error.phtml
  15. |           `-- index
  16. |               `-- index.phtml
  17. |-- library
  18. |-- public
  19. |   `-- index.php
  20. `-- tests
  21.     |-- application
  22.     |   `-- bootstrap.php
  23.     |-- library
  24.     |   `-- bootstrap.php
  25.     `-- phpunit.xml

In the above diagram, your bootstrap is in newproject/application/Bootstrap.php, and looks like the following at first:

  1. class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
  2. {
  3. }

You'll also note that a configuration file, newproject/application/configs/application.ini, is created. It has the following contents:

  1. [production]
  2. phpSettings.display_startup_errors = 0
  3. phpSettings.display_errors = 0
  4. includePaths.library = APPLICATION_PATH "/../library"
  5. bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
  6. bootstrap.class = "Bootstrap"
  7. resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"
  8.
  9. [staging : production]
  10.
  11. [testing : production]
  12. phpSettings.display_startup_errors = 1
  13. phpSettings.display_errors = 1
  14.
  15. [development : production]
  16. phpSettings.display_startup_errors = 1
  17. phpSettings.display_errors = 1

All settings in this configuration file are for use with Zend_Application and your bootstrap.

Another file of interest is the newproject/public/index.php file, which invokes Zend_Application and dispatches it.

  1. // Define path to application directory
  2. defined('APPLICATION_PATH')
  3.     || define('APPLICATION_PATH',
  4.               realpath(dirname(__FILE__) . '/../application'));
  5.
  6. // Define application environment
  7. defined('APPLICATION_ENV')
  8.     || define('APPLICATION_ENV',
  9.               (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV')
  10.                                          : 'production'));
  11.
  12. /** Zend_Application */
  13. require_once 'Zend/Application.php';
  14.
  15. // Create application, bootstrap, and run
  16. $application = new Zend_Application(
  17.     APPLICATION_ENV,
  18.     APPLICATION_PATH . '/configs/application.ini'
  19. );
  20. $application->bootstrap()
  21.             ->run();

To continue the quick start, please skip to the Resources section.

Adding Zend_Application to your application

The basics of Zend_Application are fairly simple:

  • Create an application/Bootstrap.php file, with the class Bootstrap.

  • Create an application/configs/application.ini configuration file with the base configuration necessary for Zend_Application.

  • Modify your public/index.php to utilize Zend_Application.

First, create your Bootstrap class. Create a file, application/Bootstrap.php, with the following contents:

  1. class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
  2. {
  3. }

Now, create your configuration. For this tutorial, we will use an INI style configuration; you may, of course, use an XML or PHP configuration file as well. Create the file application/configs/application.ini, and provide the following contents:

  1. [production]
  2. phpSettings.display_startup_errors = 0
  3. phpSettings.display_errors = 0
  4. includePaths.library = APPLICATION_PATH "/../library"
  5. bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
  6. bootstrap.class = "Bootstrap"
  7. resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"
  8.
  9. [staging : production]
  10.
  11. [testing : production]
  12. phpSettings.display_startup_errors = 1
  13. phpSettings.display_errors = 1
  14.
  15. [development : production]
  16. phpSettings.display_startup_errors = 1
  17. phpSettings.display_errors = 1

Now, let's modify your gateway script, public/index.php. If the file does not exist, create it; otherwise, replace it with the following contents:

  1. // Define path to application directory
  2. defined('APPLICATION_PATH')
  3.     || define('APPLICATION_PATH',
  4.               realpath(dirname(__FILE__) . '/../application'));
  5.
  6. // Define application environment
  7. defined('APPLICATION_ENV')
  8.     || define('APPLICATION_ENV',
  9.               (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV')
  10.                                          : 'production'));
  11.
  12. // Typically, you will also want to add your library/ directory
  13. // to the include_path, particularly if it contains your ZF installed
  14. set_include_path(implode(PATH_SEPARATOR, array(
  15.     dirname(dirname(__FILE__)) . '/library',
  16.     get_include_path(),
  17. )));
  18.
  19. /** Zend_Application */
  20. require_once 'Zend/Application.php';
  21.
  22. // Create application, bootstrap, and run
  23. $application = new Zend_Application(
  24.     APPLICATION_ENV,
  25.     APPLICATION_PATH . '/configs/application.ini'
  26. );
  27. $application->bootstrap()
  28.             ->run();

You may note that the application environment constant value looks for an environment variable "APPLICATION_ENV". We recommend setting this in your web server environment. In Apache, you can set this either in your vhost definition, or in your .htaccess file. We recommend the following contents for your public/.htaccess file:

  1. SetEnv APPLICATION_ENV development
  2.
  3. RewriteEngine On
  4. RewriteCond %{REQUEST_FILENAME} -s [OR]
  5. RewriteCond %{REQUEST_FILENAME} -l [OR]
  6. RewriteCond %{REQUEST_FILENAME} -d
  7. RewriteRule ^.*$ - [NC,L]
  8. RewriteRule ^.*$ index.php [NC,L]

Note: Learn about mod_rewrite
 The above rewrite rules allow access to any file under your virtual host's document root. If there are files you do not want exposed in this way, you may want to be more restrictive in your rules. Go to the Apache website to » learn more about mod_rewrite.

At this point, you're all set to start taking advantage of Zend_Application.

Adding and creating resources

If you followed the directions above, then your bootstrap class will be utilizing a front controller, and when it is run, it will dispatch the front controller. However, in all likelihood, you'll need a little more configuration than this.

In this section, we'll look at adding two resources to your application. First, we'll set up your layouts, and then we'll customize your view object.

One of the standard resources provided with Zend_Application is the "layout" resource. This resource expects you to define configuration values which it will then use to configure your Zend_Layout instance.

To use it, all we need to do is update the configuration file.

  1. [production]
  2. phpSettings.display_startup_errors = 0
  3. phpSettings.display_errors = 0
  4. bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
  5. bootstrap.class = "Bootstrap"
  6. resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"
  7. ; ADD THE FOLLOWING LINES
  8. resources.layout.layout = "layout"
  9. resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts"
  10.
  11. [staging : production]
  12.
  13. [testing : production]
  14. phpSettings.display_startup_errors = 1
  15. phpSettings.display_errors = 1
  16.
  17. [development : production]
  18. phpSettings.display_startup_errors = 1
  19. phpSettings.display_errors = 1

If you haven't already, create the directory application/layouts/scripts/, and the file layout.phtml within that directory. A good starting layout is as follows (and ties in with the view resource covered next):

  1. <?php echo $this->doctype() ?>
  2. <html>
  3. <head>
  4.     <?php echo $this->headTitle() ?>
  5.     <?php echo $this->headLink() ?>
  6.     <?php echo $this->headStyle() ?>
  7.     <?php echo $this->headScript() ?>
  8. </head>
  9. <body>
  10.     <?php echo $this->layout()->content ?>
  11. </body>
  12. </html>

At this point, you will now have a working layout.

Now, we'll add a custom view resource. When initializing the view, we'll want to set the HTML DocType and a default value for the title to use in the HTML head. This can be accomplished by editing your Bootstrap class to add a method:

  1. class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
  2. {
  3.     protected function _initView()
  4.     {
  5.         // Initialize view
  6.         $view = new Zend_View();
  7.         $view->doctype('XHTML1_STRICT');
  8.         $view->headTitle('My First Zend Framework Application');
  9.
  10.         // Add it to the ViewRenderer
  11.         $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper(
  12.             'ViewRenderer'
  13.         );
  14.         $viewRenderer->setView($view);
  15.
  16.         // Return it, so that it can be stored by the bootstrap
  17.         return $view;
  18.     }
  19. }

This method will be automatically executed when you bootstrap the application, and will ensure your view is initialized according to your application needs.

Next steps with Zend_Application

The above should get you started with Zend_Application and creating your application bootstrap. From here, you should start creating resource methods, or, for maximum re-usability, resource plugin classes. Continue reading to learn more!

简介
Zend_Application
Zend Framework手册 中文版
Theory of Operation
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Application
  • 简介
  • Zend_Application Quick Start
  • Theory of Operation
  • Examples
  • Core Functionality
  • Available Resource Plugins


Theory of Operation - Zend Framework Manual

Zend_Application Quick Start
Zend_Application
Zend Framework手册 中文版
Examples

Theory of Operation

Getting an MVC application configured and ready to dispatch has required an increasing amount of code as more features become available: setting up the database, configuring your view and view helpers, configuring your layouts, registering plugins, registering action helpers, and more.

Additionally, you will often want to reuse the same code to bootstrap your tests, a cronjob, or a service script. While it's possible to simply include your bootstrap script, oftentimes there are initializations that are environment specific – you may not need the MVC for a cronjob, or just the DB layer for a service script.

Zend_Application aims to make this easier and to promote reuse by encapsulating bootstrapping into OOP paradigms.

Zend_Application is broken into three realms:

  • Zend_Application: loads the PHP environment, including include_paths and autoloading, and instantiates the requested bootstrap class.

  • Zend_Application_Bootstrap: provides interfaces for bootstrap classes. Zend_Application_Bootstrap_Bootstrap provides common functionality for most bootstrapping needs, including dependency checking algorithms and the ability to load bootstrap resources on demand.

  • Zend_Application_Resource provides an interface for standard bootstrapping resources that can be loaded on demand by a bootstrap instance, as well as several default resource implementations.

Developers create a bootstrap class for their application, extending Zend_Application_Bootstrap_Bootstrap or implementing (minimally) Zend_Application_Bootstrap_Bootstrapper. The entry point (e.g., public/index.php) will load Zend_Application, and instantiate it by passing:

  • The current environment

  • Options for bootstrapping

The bootstrap options include the path to the file containing the bootstrap class and optionally:

  • Any extra include_paths to set

  • Any additional autoloader namespaces to register

  • Any php.ini settings to initialize

  • The class name for the bootstrap class (if not "Bootstrap")

  • Resource prefix to path pairs to use

  • Any resources to use (by class name or short name)

  • Additional path to a configuration file to load

  • Additional configuration options

Options may be an array, a Zend_Config object, or the path to a configuration file.

Bootstrapping

Zend_Application's second area of responsibility is executing the application bootstrap. Bootstraps minimally need to implement Zend_Application_Bootstrap_Bootstrapper, which defines the following API:

  1. interface Zend_Application_Bootstrap_Bootstrapper
  2. {
  3.     public function __construct($application);
  4.     public function setOptions(array $options);
  5.     public function getApplication();
  6.     public function getEnvironment();
  7.     public function getClassResources();
  8.     public function getClassResourceNames();
  9.     public function bootstrap($resource = null);
  10.     public function run();
  11. }

This API allows the bootstrap to accept the environment and configuration from the application object, report the resources its responsible for bootstrapping, and then bootstrap and run the application.

You can implement this interface on your own, extend Zend_Application_Bootstrap_BootstrapAbstract, or use Zend_Application_Bootstrap_Bootstrap.

Besides this functionality, there are a number of other areas of concern you should familiarize yourself with.

Resource Methods

The Zend_Application_Bootstrap_BootstrapAbstract implementation provides a simple convention for defining class resource methods. Any protected method beginning with a name prefixed with _init will be considered a resource method.

To bootstrap a single resource method, use the bootstrap() method, and pass it the name of the resource. The name will be the method name minus the _init prefix.

To bootstrap several resource methods, pass an array of names. Too bootstrap all resource methods, pass nothing.

Take the following bootstrap class:

  1. class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
  2. {
  3.     protected function _initFoo()
  4.     {
  5.         // ...
  6.     }
  7.
  8.     protected function _initBar()
  9.     {
  10.         // ...
  11.     }
  12.
  13.     protected function _initBaz()
  14.     {
  15.         // ...
  16.     }
  17. }

To bootstrap just the _initFoo() method, do the following:

  1. $bootstrap->bootstrap('foo');

To bootstrap the _initFoo() and _initBar() methods, do the following:

  1. $bootstrap->bootstrap(array('foo', 'bar'));

To bootstrap all resource methods, call bootstrap() with no arguments:

  1. $bootstrap->bootstrap();

Bootstraps that use resource plugins

To make your bootstraps more re-usable, we have provided the ability to push your resources into resource plugin classes. This allows you to mix and match resources simply via configuration. We will cover how to create resources later; in this section we will show you how to utilize them only.

If your bootstrap should be capable of using resource plugins, you will need to implement an additional interface, Zend_Application_Bootstrap_ResourceBootstrapper. This interface defines an API for locating, registering, and loading resource plugins:

  1. interface Zend_Application_Bootstrap_ResourceBootstrapper
  2. {
  3.     public function registerPluginResource($resource, $options = null);
  4.     public function unregisterPluginResource($resource);
  5.     public function hasPluginResource($resource);
  6.     public function getPluginResource($resource);
  7.     public function getPluginResources();
  8.     public function getPluginResourceNames();
  9.     public function setPluginLoader(Zend_Loader_PluginLoader_Interface $loader);
  10.     public function getPluginLoader();
  11. }

Resource plugins basically provide the ability to create resource intializers that can be re-used between applications. This allows you to keep your actual bootstrap relatively clean, and to introduce new resources without needing to touch your bootstrap itself.

Zend_Application_Bootstrap_BootstrapAbstract (and Zend_Application_Bootstrap_Bootstrap by extension) implement this interface as well, allowing you to utilize resource plugins.

To utilize resource plugins, you must specify them in the options passed to the application object and/or bootstrap. These options may come from a configuration file, or be passed in manually. Options will be of key to options pairs, with the key representing the resource name. The resource name will be the segment following the class prefix. For example, the resources shipped with Zend Framework have the class prefix "Zend_Application_Resource_"; anything following this would be the name of the resource. As an example,

  1. $application = new Zend_Application(APPLICATION_ENV, array(
  2.     'resources' => array(
  3.         'FrontController' => array(
  4.             'controllerDirectory' => APPLICATION_PATH . '/controllers',
  5.         ),
  6.     ),
  7. ));

This indicates that the "FrontController" resource should be used, with the options specified.

If you begin writing your own resource plugins, or utilize third-party resource plugins, you will need to tell your bootstrap where to look for them. Internally, the bootstrap utilizes Zend_Loader_PluginLoader, so you will only need to indicate the common class prefix an path pairs.

As an example, let's assume you have custom resource plugins in APPLICATION_PATH/resources/ and that they share the common class prefix of My_Resource. You would then pass that information to the application object as follows:

  1. $application = new Zend_Application(APPLICATION_ENV, array(
  2.     'pluginPaths' => array(
  3.         'My_Resource' => APPLICATION_PATH . '/resources/',
  4.     ),
  5.     'resources' => array(
  6.         'FrontController' => array(
  7.             'controllerDirectory' => APPLICATION_PATH . '/controllers',
  8.         ),
  9.     ),
  10. ));

You would now be able to use resources from that directory.

Just like resource methods, you use the bootstrap() method to execute resource plugins. Just like with resource methods, you can specify either a single resource plugin, multiple plugins (via an array), or all plugins. Additionally, you can mix and match to execute resource methods as well.

  1. // Execute one:
  2. $bootstrap->bootstrap('FrontController');
  3.
  4. // Execute several:
  5. $bootstrap->bootstrap(array('FrontController', 'Foo'));
  6.
  7. // Execute all resource methods and plugins:
  8. $bootstrap->bootstrap();

Resource Registry

Many, if not all, of your resource methods or plugins will initialize objects, and in many cases, these objects will be needed elsewhere in your application. How can you access them?

Zend_Application_Bootstrap_BootstrapAbstract provides a local registry for these objects. To store your objects in them, you simply return them from your resources.

For maximum flexibility, this registry is referred to as a "container" internally; its only requirements are that it is an object. Resources are then registered as properties named after the resource name. By default, an instance of Zend_Registry is used, but you may also specify any other object you wish. The methods setContainer() and getContainer() may be used to manipulate the container itself. getResource($resource) can be used to fetch a given resource from the container, and hasResource($resource) to check if the resource has actually been registered.

As an example, consider a basic view resource:

  1. class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
  2. {
  3.     protected function _initView()
  4.     {
  5.         $view = new Zend_View();
  6.         // more initialization...
  7.
  8.         return $view;
  9.     }
  10. }

You can then check for it and/or fetch it as follows:

  1. // Using the has/getResource() pair:
  2. if ($bootstrap->hasResource('view')) {
  3.     $view = $bootstrap->getResource('view');
  4. }
  5.
  6. // Via the container:
  7. $container = $bootstrap->getContainer();
  8. if (isset($container->view)) {
  9.     $view = $container->view;
  10. }

Please note that the registry and also the container is not global. This means that you need access to the bootstrap in order to fetch resources. Zend_Application_Bootstrap_Bootstrap provides some convenience for this: during its run() execution, it registers itself as the front controller parameter "bootstrap", which allows you to fetch it from the router, dispatcher, plugins, and action controllers.

As an example, if you wanted access to the view resource from above within your action controller, you could do the following:

  1. class FooController extends Zend_Controller_Action
  2. {
  3.     public function init()
  4.     {
  5.         $bootstrap = $this->getInvokeArg('bootstrap');
  6.         $view = $bootstrap->getResource('view');
  7.         // ...
  8.     }
  9. }

Dependency Tracking

In addition to executing resource methods and plugins, it's necessary to ensure that these are executed once and once only; these are meant to bootstrap an application, and executing multiple times can lead to resource overhead.

At the same time, some resources may depend on other resources being executed. To solve these two issues, Zend_Application_Bootstrap_BootstrapAbstract provides a simple, effective mechanism for dependency tracking.

As noted previously, all resources -- whether methods or plugins -- are bootstrapped by calling bootstrap($resource), where $resource is the name of a resource, an array of resources, or, left empty, indicates all resources should be run.

If a resource depends on another resource, it should call bootstrap() within its code to ensure that resource has been executed. Subsequent calls to it will then be ignored.

In a resource method, such a call would look like this:

  1. class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
  2. {
  3.     protected function _initRequest()
  4.     {
  5.         // Ensure the front controller is initialized
  6.         $this->bootstrap('FrontController');
  7.
  8.         // Retrieve the front controller from the bootstrap registry
  9.         $front = $this->getResource('FrontController');
  10.
  11.         $request = new Zend_Controller_Request_Http();
  12.         $request->setBaseUrl('/foo');
  13.         $front->setRequest($request);
  14.
  15.         // Ensure the request is stored in the bootstrap registry
  16.         return $request;
  17.     }
  18. }

Resource Plugins

As noted previously, a good way to create re-usable bootstrap resources and to offload much of your coding to discrete classes is to utilize resource plugins. While Zend Framework ships with a number of standard resource plugins, the intention is that developers should write their own to encapsulate their own initialization needs.

Resource plugins need only implement Zend_Application_Resource_Resource, or, more simply still, extend Zend_Application_Resource_ResourceAbstract. The basic interface is simply this:

  1. interface Zend_Application_Resource_Resource
  2. {
  3.     public function __construct($options = null);
  4.     public function setBootstrap(
  5.         Zend_Application_Bootstrap_Bootstrapper $bootstrap
  6.     );
  7.     public function getBootstrap();
  8.     public function setOptions(array $options);
  9.     public function getOptions();
  10.     public function init();
  11. }

The interface defines simply that a resource plugin should accept options to the constructor, have mechanisms for setting and retrieving options, have mechanisms for setting and retrieving the bootstrap object, and an initialization method.

As an example, let's assume you have a common view intialization you use in your applications. You have a common doctype, CSS and JavaScript, and you want to be able to pass in a base document title via configuration. Such a resource plugin might look like this:

  1. class My_Resource_View extends Zend_Application_Resource_ResourceAbstract
  2. {
  3.     protected $_view;
  4.
  5.     public function init()
  6.     {
  7.         // Return view so bootstrap will store it in the registry
  8.         return $this->getView();
  9.     }
  10.
  11.     public function getView()
  12.     {
  13.         if (null === $this->_view) {
  14.             $options = $this->getOptions();
  15.             $title   = '';
  16.             if (array_key_exists('title', $options)) {
  17.                 $title = $options['title'];
  18.                 unset($options['title']);
  19.             }
  20.
  21.             $view = new Zend_View($options);
  22.             $view->doctype('XHTML1_STRICT');
  23.             $view->headTitle($title);
  24.             $view->headLink()->appendStylesheet('/css/site.css');
  25.             $view->headScript()->appendfile('/js/analytics.js');
  26.
  27.             $viewRenderer =
  28.                 Zend_Controller_Action_HelperBroker::getStaticHelper(
  29.                     'ViewRenderer'
  30.                 );
  31.             $viewRenderer->setView($view);
  32.
  33.             $this->_view = $view;
  34.         }
  35.         return $this->_view;
  36.     }
  37. }

As long as you register the prefix path for this resource plugin, you can then use it in your application. Even better, because it uses the plugin loader, you are effectively overriding the shipped "View" resource plugin, ensuring that your own is used instead.

Zend_Application Quick Start
Zend_Application
Zend Framework手册 中文版
Examples
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Application
  • 简介
  • Zend_Application Quick Start
  • Theory of Operation
  • Examples
  • Core Functionality
  • Available Resource Plugins


Examples - Zend Framework Manual

Theory of Operation
Zend_Application
Zend Framework手册 中文版
Core Functionality

Examples

The Bootstrap class itself will typically be fairly minimal; often, it will simply be an empty stub extending the base bootstrap class:

  1. class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
  2. {
  3. }

With a corresponding configuration file:

  1. ; APPLICATION_PATH/configs/application.ini
  2. [production]
  3. bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
  4. bootstrap.class = "Bootstrap"
  5. resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"
  6.
  7. [testing : production]
  8. [development : production]

However, should custom initialization be necessary, you have two choices. First, you can write methods prefixed with _init to specify discrete code to bootstrap. These methods will be called by bootstrap(), and can also be called as if they were public methods: bootstrap<resource>(). They should accept an optional array of options.

If your resource method returns a value, it will be stored in a container in the bootstrap. This can be useful when different resources need to interact (such as one resource injecting itself into another). The method getResource() can then be used to retrieve those values.

The example below shows a resource method for initializing the request object. It makes use of dependency tracking (it depends on the front controller resource), fetching a resource from the bootstrap, and returning a value to store in the bootstrap.

  1. class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
  2. {
  3.     protected function _initRequest()
  4.     {
  5.         // Ensure front controller instance is present, and fetch it
  6.         $this->bootstrap('FrontController');
  7.         $front = $this->getResource('FrontController');
  8.
  9.         // Initialize the request object
  10.         $request = new Zend_Controller_Request_Http();
  11.         $request->setBaseUrl('/foo');
  12.
  13.         // Add it to the front controller
  14.         $front->setRequest($request);
  15.
  16.         // Bootstrap will store this value in the 'request' key of its container
  17.         return $request;
  18.     }
  19. }

Note in this example the call to bootstrap(); this ensures that the front controller has been initialized prior to calling this method. That call may trigger either a resource or another method in the class.

The other option is to use resource plugins. Resource plugins are objects that perform specific initializations, and may be specified:

  • When instantiating the Zend_Application object

  • During initialization of the bootstrap object

  • By explicitly enabling them via method calls to the bootstrap object

Resource plugins implement Zend_Application_Resource_ResourceAbstract, which defines simply that they allow injection of the caller and options, and that they have an init() method. As an example, a custom "View" bootstrap resource might look like the following:

  1. class My_Bootstrap_Resource_View
  2.     extends Zend_Application_Resource_ResourceAbstract
  3. {
  4.     public function init()
  5.     {
  6.         $view = new Zend_View($this->getOptions());
  7.         Zend_Dojo::enableView($view);
  8.
  9.         $view->doctype('XHTML1_STRICT');
  10.         $view->headTitle()->setSeparator(' - ')->append('My Site');
  11.         $view->headMeta()->appendHttpEquiv('Content-Type',
  12.                                            'text/html; charset=utf-8');
  13.
  14.         $view->dojo()->setDjConfigOption('parseOnLoad', true)
  15.                      ->setLocalPath('/js/dojo/dojo.js')
  16.                      ->registerModulePath('../spindle', 'spindle')
  17.                      ->addStylesheetModule('spindle.themes.spindle')
  18.                      ->requireModule('spindle.main')
  19.                      ->disable();
  20.
  21.         $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper(
  22.             'ViewRenderer'
  23.         );
  24.         $viewRenderer->setView($view);
  25.
  26.         return $view;
  27.     }
  28. }

To tell the bootstrap to use this, you would need to provide either the class name of the resource plugin, or a combination of a plugin loader prefix path and the short name of the resource plugin (e.g, "view"):

  1. $application = new Zend_Application(
  2.     APPLICATION_ENV,
  3.     array(
  4.         'resources' => array(
  5.             'My_Bootstrap_Resource_View' => array(), // full class name; OR
  6.             'view' => array(),                       // short name
  7.
  8.             'FrontController' => array(
  9.                 'controllerDirectory' => APPLICATION_PATH . '/controllers',
  10.             ),
  11.         ),
  12.
  13.         // For short names, define plugin paths:
  14.         'pluginPaths = array(
  15.             'My_Bootstrap_Resource' => 'My/Bootstrap/Resource',
  16.         )
  17.     )
  18. );

Resource plugins can call on other resources and initializers by accessing the parent bootstrap:

  1. class My_Bootstrap_Resource_Layout
  2.     extends Zend_Application_Resource_ResourceAbstract
  3. {
  4.     public function init()
  5.     {
  6.         // ensure view is initialized...
  7.         $this->getBootstrap()->bootstrap('view');
  8.
  9.         // Get view object:
  10.         $view = $this->getBootstrap()->getResource('view');
  11.
  12.         // ...
  13.     }
  14. }

In normal usage, you would instantiate the application, bootstrap it, and run it:

  1. $application = new Zend_Application(...);
  2. $application->bootstrap()
  3.             ->run();

For a custom script, you might need to simply initialize specific resources:

  1. $application = new Zend_Application(...);
  2. $application->getBootstrap()->bootstrap('db');
  3.
  4. $service = new Zend_XmlRpc_Server();
  5. $service->setClass('Foo');  // uses database...
  6. echo $service->handle();

Instead of using the bootstrap() method to call the internal methods or resources, you may also use overloading:

  1. $application = new Zend_Application(...);
  2. $application->getBootstrap()->bootstrapDb();
Theory of Operation
Zend_Application
Zend Framework手册 中文版
Core Functionality
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Application
  • 简介
  • Zend_Application Quick Start
  • Theory of Operation
  • Examples
  • Core Functionality
  • Available Resource Plugins


Core Functionality - Zend Framework Manual

Examples
Zend_Application
Zend Framework手册 中文版
Available Resource Plugins

Core Functionality

Here you'll find API-like documentation about all core components of Zend_Application.

Zend_Application

Zend_Application provides the base functionality of the component, and the entry point to your Zend Framework application. It's purpose is two-fold: to setup the PHP environment (including autoloading), and to execute your application bootstrap.

Typically, you will pass all configuration to the Zend_Application constructor, but you can also configure the object entirely using its own methods. This reference is intended to illustrate both use cases.

Zend_Application options
Option | Description
phpSettings | Array of php.ini settings to use. Keys should be the php.ini keys.
includePaths | Additional paths to prepend to the include_path. Should be an array of paths.
autoloaderNamespaces | Array of additional namespaces to register with the Zend_Loader_Autoloader instance.
bootstrap | Either the string path to the bootstrap class, or an array with elements for the 'path' and 'class' for the application bootstrap.

Note: Option names
 Please note that option names are case insensitive.

Zend_Application Methods
Method Return Value Parameters Description
__construct($environment, $options = null) Void

  • $environment: required,. String representing the current application environment. Typical strings might include "development", "testing", "qa", or "production", but will be defined by your organizational requirements.

  • $options: optional. Argument may be one of the following values:

    • String : path to a Zend_Config file to load as configuration for your application. $environment will be used to determine what section of the configuration to pull.

    • Array : associative array of configuration data for your application.

    • Zend_Config: configuration object instance.

Constructor. Arguments are as described, and will be used to set initial object state. An instance of Zend_Loader_Autoloader is registered during instantiation. Options passed to the constructor are passed to setOptions().

getEnvironment() String N/A

Retrieve the environment string passed to the constructor.

getAutoloader() Zend_Loader_Autoloader N/A

Retrieve the Zend_Loader_Autoloader instance registered during instantiation.

setOptions(array $options) Zend_Application

  • $options: required. An array of application options.

All options are stored internally, and calling the method multiple times will merge options. Options matching the various setter methods will be passed to those methods. As an example, the option "phpSettings" will then be passed to setPhpSettings(). (Option names are case insensitive.)

getOptions() Array N/A

Retrieve all options used to initialize the object; could be used to cache Zend_Config options to a serialized format between requests.

hasOption($key) Boolean

  • $key: String option key to lookup

Determine whether or not an option with the specified key has been registered. Keys are case insensitive.

getOption($key) Mixed

  • $key: String option key to lookup

Retrieve the option value of a given key. Returns NULL if the key does not exist.

setPhpSettings(array $settings, $prefix = '') Zend_Application

  • $settings: required. Associative array of PHP INI settings.

  • $prefix: optional. String prefix with which to prepend option keys. Used internally to allow mapping nested arrays to dot-separated php.ini keys. In normal usage, this argument should never be passed by a user.

Set run-time php.ini settings. Dot-separated settings may be nested hierarchically (which may occur with INI Zend_Config files) via an array-of-arrays, and will still resolve correctly.

setAutoloaderNamespaces(array $namespaces) Zend_Application

  • $namespaces: required. Array of strings representing the namespaces to register with the Zend_Loader_Autoloader instance.

Register namespaces with the Zend_Loader_Autoloader instance.

setBootstrap($path, $class = null) Zend_Application

  • $path: required. May be either a Zend_Application_Bootstrap_Bootstrapper instance, a string path to the bootstrap class, an associative array of classname => filename, or an associative array with the keys 'class' and 'path'.

  • $class: optional. If $path is a string, $class may be specified, and should be a string class name of the class contained in the file represented by path.

getBootstrap() NULL | Zend_Application_Bootstrap_Bootstrapper N/A

Retrieve the registered bootstrap instance.

bootstrap() Void N/A

Call the bootstrap's bootstrap() method to bootstrap the application.

run() Void N/A

Call the bootstrap's run() method to dispatch the application.

Zend_Application_Bootstrap_Bootstrapper

Zend_Application_Bootstrap_Bootstrapper is the base interface all bootstrap classes must implement. The base functionality is aimed at configuration, identifying resources, bootstrapping (either individual resources or the entire application), and dispatching the application.

The following methods make up the definition of the interface.

Zend_Application_Bootstrap_Bootstrapper Interface
Method Return Value Parameters Description
__construct($application) Void

  • $application: required. Should accept a Zend_Application or a Zend_Application_Bootstrap_Bootstrapper object as the sole argument.

Constructor. Accepts a single argument, which should be a Zend_Application object, or another bootstrap object.

setOptions(array $options) Zend_Application_Bootstrap_Bootstrapper

  • $options: required. Array of options to set.

Typically, any option that has a matching setter will invoke that setter; otherwise, the option will simply be stored for later retrieval.

getApplication() Zend_Application | Zend_Application_Bootstrap_Bootstrapper N/A

Retrieve the application or bootstrap object passed via the constructor.

getEnvironment() String N/A

Retrieve the environment string registered with the parent application or bootstrap object.

getClassResources() Array N/A

Retrieve a list of available resource initializer names as defined in the class. This may be implementation specific.

bootstrap($resource = null) Mixed

  • $resource: optional.

If $resource is empty, execute all bootstrap resources. If a string, execute that single resource; if an array, execute each resource in the array.

run() Void N/A

Defines what application logic to run after bootstrapping.

Zend_Application_Bootstrap_ResourceBootstrapper

Zend_Application_Bootstrap_ResourceBootstrapper is an interface to use when a bootstrap class will be loading external resources -- i.e., one or more resources will not be defined directly in the class, but rather via plugins. It should be used in conjunction with Zend_Application_Bootstrap_Bootstrapper; Zend_Application_Bootstrap_BootstrapAbstract implements this functionality.

The following methods make up the definition of the interface.

Zend_Application_Bootstrap_ResourceBootstrapper Interface
Method Return Value Parameters Description
registerPluginResource($resource, $options = null) Zend_Application_Bootstrap_ResourceBootstrapper

  • $resource: required. A resource name or Zend_Application_Resource_Resource object.

  • $options: optional. An array or Zend_Config object to pass to the resource on instantiation.

Register a resource with the class, providing optional configuration to pass to the resource.

unregisterPluginResource($resource) Zend_Application_Bootstrap_ResourceBootstrapper

  • $resource: required. Name of a resource to unregister from the class.

Remove a plugin resource from the class.

hasPluginResource($resource) Boolean

  • $resource: required. Name of the resource.

Determine if a specific resource has been registered with the class.

getPluginResource($resource) Zend_Application_Resource_Resource

  • $resource: required. Name of a resource to retrieve (string).

Retrieve a plugin resource instance by name.

getPluginResourceNames() Array N/A

Retrieve a list of all registered plugin resource names.

setPluginLoader(Zend_Loader_PluginLoader_Interface $loader) Zend_Application_Bootstrap_ResourceBootstrapper

  • $loader: required. Plugin loader instance to use when resolving plugin names to classes.

Register a plugin loader instance to use when resolving plugin class names.

getPluginLoader() Zend_Loader_PluginLoader_Interface N/A

Retrieve the registered plugin loader.

Zend_Application_Bootstrap_BootstrapAbstract

Zend_Application_Bootstrap_BootstrapAbstract is an abstract class which provides the base functionality of a common bootstrap. It implements both Zend_Application_Bootstrap_Bootstrapper and Zend_Application_Bootstrap_ResourceBootstrapper.

Zend_Application_Bootstrap_BootstrapAbstract Methods
Method Return Value Parameters Description
__construct($application) Void

  • $application: required. Accepts either a Zend_Application or a Zend_Application_Bootstrap_Bootstrapper object as the sole argument.

Constructor. Accepts a single argument, which should be a Zend_Application object, or another bootstrap object.

setOptions(array $options) Zend_Application_Bootstrap_Bootstrapper

  • $options: required. Array of options to set.

Any option that has a matching setter will invoke that setter; otherwise, the option will simply be stored for later retrieval. As an example, if your extending class defined a setFoo() method, the option 'foo' would pass the value to that method.

Two additional, special options keys may also be used. pluginPaths may be used to specify prefix paths to plugin resources; it should be an array of class prefix to filesystem path pairs. resources may be used to specify plugin resources to use, and should consist of plugin resource to instantiation options pairs.

getOptions() Array N/A

Returns all options registered via setOptions().

hasOption($key) Boolean

  • $key: required. Option key to test.

Determine if an option key is present.
getOption($key) Mixed

  • $key: required. Option key to retrieve.

Retrieve the value associated with an option key; returns NULL if no option is registered with that key.

setApplication(Zend_Application | Zend_Application_Bootstrap_Bootstrapper $application) Zend_Application_Bootstrap_BootstrapAbstract

  • $application: required.

Register the parent application or bootstrap object.

getApplication() Zend_Application | Zend_Application_Bootstrap_Bootstrapper N/A

Retrieve the application or bootstrap object passed via the constructor.

getEnvironment() String N/A

Retrieve the environment string registered with the parent application or bootstrap object.

getClassResources() Array N/A

Retrieve a list of available resource initializer names as defined in the class. This may be implementation specific.

getContainer() Object N/A

Retrieves the container that stores resources. If no container is currently registered, it registers a Zend_Registry instance before returning it.

setContainer($container) Zend_Application_Bootstrap_BootstrapAbstract

  • $container, required. An object in which to store resources.

Provide a container in which to store resources. When a resource method or plugin returns a value, it will be stored in this container for later retrieval.

hasResource($name) Boolean

  • $name, required. Name of a resource to check.

When a resource method or plugin returns a value, it will be stored in the resource container (see getContainer() and setContainer(). This method will indicate whether or not a value for that resource has been set.

getResource($name) Mixed

  • $name, required. Name of a resource to fetch.

When a resource method or plugin returns a value, it will be stored in the resource container (see getContainer() and setContainer(). This method will retrieve a resources from the container.

bootstrap($resource = null) Mixed

  • $resource: optional.

If $resource is empty, execute all bootstrap resources. If a string, execute that single resource; if an array, execute each resource in the array.

This method can be used to run individual bootstraps either defined in the class itself or via resource plugin classes. A resource defined in the class will be run in preference over a resource plugin in the case of naming conflicts.

run() Void N/A

Defines what application logic to run after bootstrapping.

__call($method, $args) Mixed

  • $method: required. The method name to call.

  • $args: required. Array of arguments to use in the method call.

Provides convenience to bootstrapping individual resources by allowing you to call 'bootstrap<ResourceName>()' instead of using the bootstrap() method.

Zend_Application_Bootstrap_Bootstrap

Zend_Application_Bootstrap_Bootstrap is a concrete implementation of Zend_Application_Bootstrap_BootstrapAbstract. It's primary feature are that it registers the Front Controller resource, and that the run() method first checks that a default module is defined and then dispatches the front controller.

In most cases, you will want to extend this class for your bootstrapping needs, or simply use this class and provide a list of resource plugins to utilize.

Enabling Application Autoloading

Additionally, this bootstrap implementation provides the ability to specify the "namespace" or class prefix for resources located in its tree, which will enable autoloading of various application resources; essentially, it instantiates a Zend_Application_Module_Autoloader object, providing the requested namespace and the bootstrap's directory as arguments. You may enable this functionality by providing a namespace to the "appnamespace" configuration option. As an INI example:

  1. appnamespace = "Application"

Or in XML:

  1. <appnamespace>Application</appnamespace>

By default, Zend_Tool will enable this option with the value "Application".

Alternately, you can simply define the $_appNamespace property of your bootstrap class with the appropriate value:

  1. class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
  2. {
  3.     protected $_appNamespace = 'Application';
  4. }

Zend_Application_Resource_Resource

Zend_Application_Resource_Resource is an interface for plugin resources used with bootstrap classes implementing Zend_Application_Bootstrap_ResourceBootstrapper. Resource plugins are expected to allow configuration, be bootstrap aware, and implement a strategy pattern for initializing the resource.

Zend_Application_Resource_Resource Interface
Method Return Value Parameters Description
__construct($options = null) Void

  • $options: optional. Options with which to set resource state.

The constructor should allow passing options with which to initialize state.

setBootstrap(Zend_Application_Bootstrap_Bootstrapper $bootstrap) Zend_Application_Resource_Resource

  • $bootstrap: required. Parent bootstrap initializing this resource.

Should allow registering the parent bootstrap object.

getBootstrap() Zend_Application_Bootstrap_Bootstrapper N/A

Retrieve the registered bootstrap instance.

setOptions(array $options) Zend_Application_Resource_Resource

  • $options: required. Options with which to set state.

Set resource state.

getOptions() Array N/A

Retrieve registered options.

init() Mixed N/A

Strategy pattern: run initialization of the resource.

Zend_Application_Resource_ResourceAbstract

Zend_Application_Resource_ResourceAbstract is an abstract class implementing Zend_Application_Resource_Resource, and is a good starting point for creating your own custom plugin resources.

Note: this abstract class does not implement the init() method; this is left for definition in concrete extensions of the class.

Zend_Application_Resource_ResourceAbstract Methods
Method Return Value Parameters Description
__construct($options = null) Void

  • $options: optional. Options with which to set resource state.

The constructor should allow passing options with which to initialize state.

setBootstrap(Zend_Application_Bootstrap_Bootstrapper $bootstrap) Zend_Application_Resource_ResourceAbstract

  • $bootstrap: required. Parent bootstrap initializing this resource.

Should allow registering the parent bootstrap object.

getBootstrap() Zend_Application_Bootstrap_Bootstrapper N/A

Retrieve the registered bootstrap instance.

setOptions(array $options) Zend_Application_Resource_ResourceAbstract

  • $options: required. Options with which to set state.

Set resource state.

getOptions() Array N/A

Retrieve registered options.

Resource Names

When registering plugin resources, one issue that arises is how you should refer to them from the parent bootstrap class. There are three different mechanisms that may be used, depending on how you have configured the bootstrap and its plugin resources.

First, if your plugins are defined within a defined prefix path, you may refer to them simply by their "short name" -- i.e., the portion of the class name following the class prefix. As an example, the class "Zend_Application_Resource_View" may be referenced as simply "View", as the prefix path "Zend_Application_Resource" is already registered. You may register them using the full class name or the short name:

  1. $app = new Zend_Application(APPLICATION_ENV, array(
  2.     'pluginPaths' => array(
  3.         'My_Resource' => 'My/Resource/',
  4.     ),
  5.     'resources' => array(
  6.         // if the following class exists:
  7.         'My_Resource_View' => array(),
  8.
  9.         // then this is equivalent:
  10.         'View' => array(),
  11.     ),
  12. ));

In each case, you can then bootstrap the resource and retrieve it later using the short name:

  1. $bootstrap->bootstrap('view');
  2. $view = $bootstrap->getResource('view');

Second, if no matching plugin path is defined, you may still pass a resource by the full class name. In this case, you can reference it using the resource's full class name:

  1. $app = new Zend_Application(APPLICATION_ENV, array(
  2.     'resources' => array(
  3.         // This will load the standard 'View' resource:
  4.         'View' => array(),
  5.
  6.         // While this loads a resource with a specific class name:
  7.         'My_Resource_View' => array(),
  8.     ),
  9. ));

Obviously, this makes referencing the resource much more verbose:

  1. $bootstrap->bootstrap('My_Resource_View');
  2. $view = $bootstrap->getResource('My_Resource_View');

This brings us to the third option. You can specify an explicit name that a given resource class will register as. This can be done by adding a public $_explicitType property to the resource plugin class, with a string value; that value will then be used whenever you wish to reference the plugin resource via the bootstrap. As an example, let's define our own view class:

  1. class My_Resource_View extends Zend_Application_Resource_ResourceAbstract
  2. {
  3.     public $_explicitType = 'My_View';
  4.
  5.     public function init()
  6.     {
  7.         // do some initialization...
  8.     }
  9. }

We can then bootstrap that resource or retrieve it by the name "My_View":

  1. $bootstrap->bootstrap('My_View');
  2. $view = $bootstrap->getResource('My_View');

Using these various naming approaches, you can override existing resources, add your own, mix multiple resources to achieve complex initialization, and more.

Examples
Zend_Application
Zend Framework手册 中文版
Available Resource Plugins
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Application
  • 简介
  • Zend_Application Quick Start
  • Theory of Operation
  • Examples
  • Core Functionality
  • Available Resource Plugins


Available Resource Plugins - Zend Framework Manual

Core Functionality
Zend_Application
Zend Framework手册 中文版
Zend_Auth

Available Resource Plugins

Here you'll find API-like documentation about all resource plugins available by default in Zend_Application.

Zend_Application_Resource_Cachemanager

Zend_Application_Resource_Cachemanager may be utilised to configure a set of Zend_Cache option bundles for use when lazy loading caches using Zend_Cache_Manager

As the Cache Manager is a lazy loading mechanism, the options are translated to option templates used to instantiate a cache object on request.

Example #1 Sample Cachemanager resource configuration

Below is a sample INI file showing how Zend_Cache_Manager may be configured. The format is the Cachemanager resource prefix (resources.cachemanager) followed be the name to assign to an option cache template or bundle (e.g. resources.cachemanager.database) and finally followed by a typical Zend_Cache option.

  1. resources.cachemanager.database.frontend.name = Core
  2. resources.cachemanager.database.frontend.options.lifetime = 7200
  3. resources.cachemanager.database.frontend.options.automatic_serialization = true
  4. resources.cachemanager.database.backend.name = File
  5. resources.cachemanager.database.backend.options.cache_dir = "/path/to/cache"

Actually retrieving this cache from the Cache Manager is as simple as accessing an instance of the Manager and calling $cacheManager->getCache('database');.

Zend_Application_Resource_Db

Zend_Application_Resource_Db will initialize a Zend_Db adapter based on the options passed to it. By default, it also sets the adapter as the default adapter for use with Zend_Db_Table. If you want to use mutliple databases simultaneously, you can use the Multidb Resource Plugin.

The following configuration keys are recognized:

  • adapter: Zend_Db adapter type.

  • params: associative array of configuration parameters to use when retrieving the adapter instance.

  • isDefaultTableAdapter: whether or not to establish this adapter as the default table adapter.

Example #2 Sample DB adapter resource configuration

Below is an example INI configuration that can be used to initialize the DB resource.

  1. [production]
  2. resources.db.adapter = "pdo_mysql"
  3. resources.db.params.host = "localhost"
  4. resources.db.params.username = "webuser"
  5. resources.db.params.password = "XXXXXXX"
  6. resources.db.params.dbname = "test"
  7. resources.db.isDefaultTableAdapter = true

Note: Retrieving the Adapter instance
 If you choose not to make the adapter instantiated with this resource the default table adapter, how do you retrieve the adapter instance?
As with any resource plugin, you can fetch the DB resource plugin from your bootstrap:

  1. $resource = $bootstrap->getPluginResource('db');
Once you have the resource object, you can fetch the DB adapter using the getDbAdapter() method:
  1. $db = $resource->getDbAdapter();

Zend_Application_Resource_Frontcontroller

Probably the most common resource you will load with Zend_Application will be the Front Controller resource, which provides the ability to configure Zend_Controller_Front. This resource provides the ability to set arbitrary front controller parameters, specify plugins to initialize, and much more.

Once initialized, the resource assigns the $frontController property of the bootstrap to the Zend_Controller_Front instance.

Available configuration keys include the following, and are case insensitive:

  • controllerDirectory: either a string value specifying a single controller directory, or an array of module to controller directory pairs.

  • moduleControllerDirectoryName: a string value indicating the subdirectory under a module that contains controllers.

  • moduleDirectory: directory under which modules may be found.

  • defaultControllerName: base name of the default controller (normally "index").

  • defaultAction: base name of the default action (normally "index").

  • defaultModule: base name of the default module (normally "default").

  • baseUrl: explicit base URL to the application (normally auto-detected).

  • plugins: array of front controller plugin class names. The resource will instantiate each class (with no constructor arguments) and then register the instance with the front controller.

  • params: array of key to value pairs to register with the front controller.

If an unrecognized key is provided, it is registered as a front controller parameter by passing it to setParam().

Example #3 Sample Front Controller resource configuration

Below is a sample INI snippet showing how to configure the front controller resource.

  1. [production]
  2. resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"
  3. resources.frontController.moduleControllerDirectoryName = "actions"
  4. resources.frontController.moduleDirectory = APPLICATION_PATH "/modules"
  5. resources.frontController.defaultControllerName = "site"
  6. resources.frontController.defaultAction = "home"
  7. resources.frontController.defaultModule = "static"
  8. resources.frontController.baseUrl = "/subdir"
  9. resources.frontController.plugins.foo = "My_Plugin_Foo"
  10. resources.frontController.plugins.bar = "My_Plugin_Bar"
  11. resources.frontController.env = APPLICATION_ENV

Example #4 Retrieving the Front Controller in your bootstrap

Once your Front Controller resource has been initialized, you can fetch the Front Controller instance via the $frontController property of your bootstrap.

  1. $bootstrap->bootstrap('frontController');
  2. $front = $bootstrap->frontController;

Zend_Application_Resource_Layout

Zend_Application_Resource_Layout can be used to configure Zend_Layout. Configuration options are per the Zend_Layout options.

Example #5 Sample Layout configuration

Below is a sample INI snippet showing how to configure the navigation resource.

  1. resources.layout.layout = "NameOfDefaultLayout"
  2. resources.layout.layoutPath = "/path/to/layouts"

Zend_Application_Resource_Locale

Zend_Application_Resource_Locale can be used to set an application-wide locale which is then used in all classes and components which work with localization or internationalization.

There are basically three usecases for the Locale Resource Plugin. Each of them should be used depending on the applications need.

Autodetect the locale to use

Without specifying any options for Zend_Application_Resource_Locale, Zend_Locale will detect the locale, which your application will use, automatically.

This detection works because your client sends the wished language within his HTTP request. Normally the clients browser sends the languages he wants to see, and Zend_Locale uses this information for detection.

But there are 2 problems with this approach:

  • The browser could be setup to send no language

  • The user could have manually set a locale which does not exist

In both cases Zend_Locale will fallback to other mechanism to detect the locale:

  • When a locale has been set which does not exist, Zend_Locale tries to downgrade this string.

    When, for example, en_ZZ is set it will automatically be degraded to en. In this case en will be used as locale for your application.

  • When the locale could also not be detected by downgrading, the locale of your environment (web server) will be used. Most available environments from Web Hosters use en as locale.

  • When the systems locale could not be detected Zend_Locale will use it's default locale, which is set to en per default.

For more informations about locale detection take a look into this chapter on Zend_Locale's automatic detection.

Autodetect the locale and adding a own fallback

The above autodetection could lead to problems when the locale could not be detected and you want to have another default locale than en. To prevent this, Zend_Application_Resource_Locale allows you to set a own locale which will be used in the case that the locale could not be detected.

Example #6 Autodetect locale and setting a fallback

The following snippet shows how to set a own default locale which will be used when the client does not send a locale himself.

  1. ; Try to determine automatically first,
  2. ; if unsuccessful, use nl_NL as fallback.
  3. resources.locale.default = "nl_NL"

Forcing a specific locale to use

Sometimes it is useful to define a single locale which has to be used. This can be done by using the force option.

In this case this single locale will be used and the automatic detection is turned off.

Example #7 Defining a single locale to use

The following snippet shows how to set a single locale for your entire application.

  1. ; No matter what, the nl_NL locale will be used.
  2. resources.locale.default = "nl_NL"
  3. resources.locale.force = true

Zend_Application_Resource_Log

Zend_Application_Resource_Log to instantiate a Zend_Log instance with an arbitrary number of log writers. Configuration will be passed to the Zend_Log::factory() method, allowing you to specify combinations of log writers and filters. The log instance may then be retrieved from the bootstrap later in order to log events.

Example #8 Sample Log Resource Configuration

Below is a sample INI snippet showing how to configure the log resource.

  1. resources.log.stream.writerName = "Stream"
  2. resources.log.stream.writerParams.stream = APPLICATION_PATH "/../data/logs/application.log"
  3. resources.log.stream.writerParams.mode = "a"
  4. resources.log.stream.filterName = "Priority"
  5. resources.log.stream.filterParams.priority = 4

For more information on available options, please review the Zend_Log::factory() documentation.

Zend_Application_Resource_Mail

Zend_Application_Resource_Mail can be used to instantiate a transport for Zend_Mail or set the default name and address, as well as the default replyto- name and address.

When instantiating a transport, it's registered automatically to Zend_Mail. Though, by setting the transport.register directive to FALSE, this behaviour does no more occur.

Example #9 Sample Mail Resource Configuration

Below is a sample INI snippet showing how to configure the mail resource plugin.

  1. resources.mail.transport.type = smtp
  2. resources.mail.transport.host = "smtp.example.com"
  3. resources.mail.transport.auth = login
  4. resources.mail.transport.username = myUsername
  5. resources.mail.transport.password = myPassword
  6. resources.mail.transport.register = true ; True by default
  7.
  8. resources.mail.defaultFrom.email = john@example.com
  9. resources.mail.defaultFrom.name = "John Doe"
  10. resources.mail.defaultReplyTo.email = Jane@example.com
  11. resources.mail.defaultReplyTo.name = "Jane Doe"

Zend_Application_Resource_Modules

Zend_Application_Resource_Modules is used to initialize your application modules. If your module has a Bootstrap.php file in its root, and it contains a class named Module_Bootstrap (where "Module" is the module name), then it will use that class to bootstrap the module.

By default, an instance of Zend_Application_Module_Autoloader will be created for the module, using the module name and directory to initialize it.

Since the Modules resource does not take any arguments by default, in order to enable it via configuration, you need to create it as an empty array. In INI style configuration, this looks like:

  1. resources.modules[] =

In XML style configuration, this looks like:

  1. <resources>
  2.     <modules>
  3.         <!-- Placeholder to ensure an array is created -->
  4.         <placeholder />
  5.     </modules>
  6. </resources>

Using a standard PHP array, simply create it as an empty array:

  1. $options = array(
  2.     'resources' => array(
  3.         'modules' => array(),
  4.     ),
  5. );

Note: Front Controller Resource Dependency
 The Modules resource has a dependency on the Front Controller resource. You can, of course, provide your own replacement for that resource via a custom Front Controller resource class or a class initializer method -- so long as the resource plugin class ends in "Frontcontroller" or the initializer method is named "_initFrontController" (case insensitive).

Example #10 Configuring Modules

You can specify module-specific configuration using the module name as a prefix or sub-section in your configuration file.

For example, let's assume that your application has a "news" module. The following are INI and XML examples showing configuration of resources in that module.

  1. [production]
  2. news.resources.db.adapter = "pdo_mysql"
  3. news.resources.db.params.host = "localhost"
  4. news.resources.db.params.username = "webuser"
  5. news.resources.db.params.password = "XXXXXXX"
  6. news.resources.db.params.dbname = "news"
  1. <?xml version="1.0"?>
  2. <config>
  3.     <production>
  4.         <news>
  5.             <resources>
  6.                 <db>
  7.                     <adapter>pdo_mysql</adapter>
  8.                     <params>
  9.                         <host>localhost</host>
  10.                         <username>webuser</username>
  11.                         <password>XXXXXXX</password>
  12.                         <dbname>news</dbname>
  13.                     </params>
  14.                     <isDefaultAdapter>true</isDefaultAdapter>
  15.                 </db>
  16.             </resources>
  17.         </news>
  18.     </production>
  19. </config>

Example #11 Retrieving a specific module bootstrap

On occasion, you may need to retrieve the bootstrap object for a specific module -- perhaps to run discrete bootstrap methods, or to fetch the autoloader in order to configure it. This can be done using the Modules resource's getExecutedBootstraps() method.

  1. $resource = $bootstrap->getPluginResource('modules');
  2. $moduleBootstraps = $resource->getExecutedBootstraps();
  3. $newsBootstrap = $moduleBootstraps['news'];

Zend_Application_Resource_Multidb

Zend_Application_Resource_Multidb is used to initialize multiple Database connections. You can use the same options as you can with the Db Resource Plugin. However, for specifying a default connection, you can also use the 'default' directive.

Example #12 Setting up multiple Db Connections

Below is an example INI configuration that can be used to initialize two Db Connections.

  1. [production]
  2. resources.multidb.db1.adapter = "pdo_mysql"
  3. resources.multidb.db1.host = "localhost"
  4. resources.multidb.db1.username = "webuser"
  5. resources.multidb.db1.password = "XXXX"
  6. resources.multidb.db1.dbname = "db1"
  7.
  8. resources.multidb.db2.adapter = "pdo_pgsql"
  9. resources.multidb.db2.host = "example.com"
  10. resources.multidb.db2.username = "dba"
  11. resources.multidb.db2.password = "notthatpublic"
  12. resources.multidb.db2.dbname = "db2"
  13. resources.multidb.db2.default = true

Example #13 Retrieving a specific database adapter

When using this resource plugin you usually will want to retrieve a specific database. This can be done by using the resource's getDb(). The method getDb() returns an instance of a class that extends Zend_Db_Adapter_Abstract. If you have not set a default database, an exception will be thrown when this method is called without specifying a parameter.

  1. $resource = $bootstrap->getPluginResource('multidb');
  2. $db1 = $resource->getDb('db1');
  3. $db2 = $resource->getDb('db2');
  4. $defaultDb = $resource->getDb();

Example #14 Retrieving the default database adapter

Additionally, you can retrieve the default database adapter by using the method getDefaultDb(). If you have not set a default adapter, the first configured db adapter will be returned. Unless you specify FALSE as first parameter, then NULL will be returned when no default database adapter was set.

Below is an example that assumes the Multidb resource plugin has been configured with the INI sample above:

  1. $resource = $bootstrap->getPluginResource('multidb');
  2. $db2 = $resource->getDefaultDb();
  3.
  4. // Same config, but now without a default db:
  5. $db1 = $resource->getDefaultDb();
  6. $null = $resource->getDefaultDb(false); // null

Zend_Application_Resource_Navigation

Zend_Application_Resource_Navigation can be used to configure a Zend_Navigation instance. Configuration options are per the Zend_Navigation options.

Once done configuring the navigation instance, it assigns the instance to Zend_View_Helper_Navigation by default -- from which you may retrieve it later.

Example #15 Sample Navigation resource configuration

Below is a sample INI snippet showing how to configure the navigation resource.

  1. resources.navigation.pages.page1.label = "Label of the first page"
  2. resources.navigation.pages.page1.route = "Route that belongs to the first page"
  3.
  4. ; Page 2 is a subpage of page 1
  5. resources.navigation.pages.page1.pages.page2.type = "Zend_Navigation_Page_Uri"
  6. resources.navigation.pages.page1.pages.page2.label = "Label of the second page"
  7. resources.navigation.pages.page1.pages.page2.uri = "/url/to/page/2"

Zend_Application_Resource_Router

Zend_Application_Resource_Router can be used to configure the router as it is registered with the Front Controller. Configuration options are per the Zend_Controller_Router_Route options.

Example #16 Sample Router Resource configuration

Below is a sample INI snippet showing how to configure the router resource.

  1. resources.router.routes.route_id.route = "/login"
  2. resources.router.routes.route_id.defaults.module = "user"
  3. resources.router.routes.route_id.defaults.controller = "login"
  4. resources.router.routes.route_id.defaults.action = "index"
  5.
  6. ; Optionally you can also set a Chain Name Separator:
  7. resources.router.chainNameSeparator = "_"

For more information on the Chain Name Separator, please see its section.

Zend_Application_Resource_Session

Zend_Application_Resource_Session allows you to configure Zend_Session as well as optionally initialize a session SaveHandler.

To set a session save handler, simply pass the saveHandler (case insensitive) option key to the resource. The value of this option may be one of the following:

  • String : A string indicating a class implementing Zend_Session_SaveHandler_Interface that should be instantiated.

  • Array : An array with the keys "class" and, optionally, "options", indicating a class implementing Zend_Session_SaveHandler_Interface that should be instantiated and an array of options to provide to its constructor.

  • Zend_Session_SaveHandler_Interface: an object implementing this interface.

Any other option keys passed will be passed to Zend_Session::setOptions() to configure Zend_Session.

Example #17 Sample Session resource configuration

Below is a sample INI snippet showing how to configure the session resource. It sets several Zend_Session options, as well as configures a Zend_Session_SaveHandler_DbTable instance.

  1. resources.session.save_path = APPLICATION_PATH "/../data/session"
  2. resources.session.use_only_cookies = true
  3. resources.session.remember_me_seconds = 864000
  4. resources.session.saveHandler.class = "Zend_Session_SaveHandler_DbTable"
  5. resources.session.saveHandler.options.name = "session"
  6. resources.session.saveHandler.options.primary.session_id = "session_id"
  7. resources.session.saveHandler.options.primary.save_path = "save_path"
  8. resources.session.saveHandler.options.primary.name = "name"
  9. resources.session.saveHandler.options.primaryAssignment.sessionId = "sessionId"
  10. resources.session.saveHandler.options.primaryAssignment.sessionSavePath = "sessionSavePath"
  11. resources.session.saveHandler.options.primaryAssignment.sessionName = "sessionName"
  12. resources.session.saveHandler.options.modifiedColumn = "modified"
  13. resources.session.saveHandler.options.dataColumn = "session_data"
  14. resources.session.saveHandler.options.lifetimeColumn = "lifetime"

Note: Bootstrap your database first!
 If you are configuring the Zend_Session_SaveHandler_DbTable session save handler, you must first configure your database connection for it to work. Do this by either using the Db resource -- and make sure the "resources.db" key comes prior to the "resources.session" key -- or by writing your own resource that initializes the database, and specifically sets the default Zend_Db_Table adapter.

Zend_Application_Resource_View

Zend_Application_Resource_View can be used to configure a Zend_View instance. Configuration options are per the Zend_View options.

Once done configuring the view instance, it creates an instance of Zend_Controller_Action_Helper_ViewRenderer and registers the ViewRenderer with Zend_Controller_Action_HelperBroker -- from which you may retrieve it later.

Example #18 Sample View resource configuration

Below is a sample INI snippet showing how to configure the view resource.

  1. resources.view.encoding = "UTF-8"
  2. resources.view.basePath = APPLICATION_PATH "/views/scripts"
Core Functionality
Zend_Application
Zend Framework手册 中文版
Zend_Auth
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Application
  • 简介
  • Zend_Application Quick Start
  • Theory of Operation
  • Examples
  • Core Functionality
  • Available Resource Plugins


Zend_Auth - Zend Framework Manual

Available Resource Plugins
Zend Framework Reference
Zend Framework手册 中文版
简介

Zend_Auth

Table of Contents
  • 简介
  • 数据库表认证
  • 摘要式认证
  • HTTP 认证适配器
  • LDAP 认证
  • Open ID Authentication
Available Resource Plugins
Zend Framework Reference
Zend Framework手册 中文版
简介
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


简介 - Zend Framework Manual

Zend_Auth
Zend_Auth
Zend Framework手册 中文版
数据库表认证

简介

Zend_Auth 为认证（authentication）和一些通用用例情景的具体认证适配器提供了一个API。

Zend_Auth 只涉及 认证而不是授权。认证被宽松地定义为基于一些证书（credential）来确定一个实体（例如，身份）是否确实是它所声称的。授权是一个过程，它决定是否允许一个实体对其他实体进行访问、执行操作，它超出了Zend_Auth的范围。更多关于Zend Framework 授权和访问控制的信息，参见Zend_Acl.

Note: Zend_Auth 类通过它的getInstance()方法实现 Singleton 模式 - 只有一个实例可用。这意味着使用 new操作符和 clone 关键字将不能在Zend_Auth 类中工作，而要使用 Zend_Auth::getInstance()来代替。

适配器

Zend_Auth适配器被用来依靠特定的认证服务（例如LDAP、RDBMS或基于文件的存储）来认证。不同的适配器可能有不同的选项和行为，但有些基本的事情在认证适配器中是通用的。例如，接受认证证书（包括声称身份）、依靠认证服务执行查询、返回结果在Zend_Auth适配器中是通用的。

每个Zend_Auth适配器类都实现Zend_Auth_Adapter_Interface。这个接口定义了一个方法authenticate()，适配器必须为执行认证查询而实现它。在调用authenticate()之前，每个适配器必需准备就绪。这样适配器准备包括设置证书（例如，用户名和密码）并为适配器专用的配置选项定义一些值，例如为数据库表适配器做的连接设置。

下面是一个认证适配器的例子，它要求为认证设置用户名和密码。为简明扼要，其它的细节（如查询认证服务）被省略了。

class MyAuthAdapter implements Zend_Auth_Adapter_Interface
{
    /**
     * Sets username and password for authentication
     *
     * @return void
     */
    public function __construct($username, $password)
    {
        // ...
    }

    /**
     * Performs an authentication attempt
     *
     * @throws Zend_Auth_Adapter_Exception If authentication cannot
     *                                     be performed
     * @return Zend_Auth_Result
     */
    public function authenticate()
    {
        // ...
    }
}
如上面所示，authenticate()必需返回一个Zend_Auth_Result的实例（或从Zend_Auth_Result派生的一个类的实例）。如果因为某些原因认证查询不能执行，authenticate()应该抛出一个由Zend_Auth_Adapter_Exception产生的异常。

结果

为了表示一个认证尝试的结果，Zend_Auth适配器返回一个带有authenticate()的Zend_Auth_Result的实例。适配器基于结构组成Zend_Auth_Result对象，下面四个方法提供了一组基本的用户面临的通用Zend_Auth适配器结果的操作：

  • isValid() - 返回 true 当且仅当结果表示一个成功的认证尝试

  • getCode() - 返回一个 Zend_Auth_Result 常量标识符用来决定认证失败的类型或者是否认证成功。这个可以用于开发者希望区别若干认证结果类型的情形，例如，这允许开发者维护详细的认证结果统计。尽管开发这被鼓励去考虑提供这样详细的原因给用户的风险，替而代之使用一般的认证失败信息，这个功能的其它用法是由于可用性的原因提供专用的，定制的信息给用户。更多的信息，参见下面的注释。

  • getIdentity() - 返回认证尝试的身份

  • getMessages() - 返回关于认证尝试失败的数组

为了执行更多的操作，开发者可能希望基于认证结果的类型来分支化。一些开发者可能发信有用的操作是：在太多的不成功的密码尝试之后锁住帐号，在太多不存在的身份尝试后标记IP地址，并提供专用的，定制的认证结果信息给用户。下面的结果代码是可用的：

Zend_Auth_Result::SUCCESS
Zend_Auth_Result::FAILURE
Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND
Zend_Auth_Result::FAILURE_IDENTITY_AMBIGUOUS
Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID
Zend_Auth_Result::FAILURE_UNCATEGORIZED

下面的例子举例说明开发者如何分支化结果代码：

// inside of AuthController / loginAction
$result = $this->_auth->authenticate($adapter);

switch ($result->getCode()) {

    case Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND:
        /** do stuff for nonexistent identity **/
        break;

    case Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID:
        /** do stuff for invalid credential **/
        break;

    case Zend_Auth_Result::SUCCESS:
        /** do stuff for successful authentication **/
        break;

    default:
        /** do stuff for other failure **/
        break;
}

身份的持久（Persistence）

实质上，认证一个包含认证证书的请求很有用，但是维护已认证的身份并在每次请求时不需要出示认证证书也同样很重要。

HTTP是一个无连接的协议，然而，象cookie和session这样的技术已经被开发出来使在服务器端的web应用维护多请求状态变得容易。

在PHP Session 中的缺省持久（Persistence）

缺省地，Zend_Auth从使用PHP session成功的认证尝试中提供身份的持久存储。基于一个成功的认证尝试，Zend_Auth::authenticate()通过把认证结果放入持久存储中来保存身份。除非另有配置，Zend_Auth 使用名称为Zend_Auth_Storage_Session 的存储类，这个类使用Zend_Session。通过实现Zend_Auth_Storage_Interface给Zend_Auth::setStorage()提供一个对象，一个定制的类可以被替代使用。

Note: 对于特定的用例，如果身份的持久存储不合适，开发者可以放弃使用Zend_Auth类，替代地，而直接使用适配器类。

Example #1 修改 Session 名字空间

Zend_Auth_Storage_Session使用'Zend_Auth'的seesion名字空间。通过给Zend_Auth_Storage_Session的构造器传递不同的值，这个名字空间可以被替换，并且这个值被从内部传递给Zend_Session_Namespace的构造器。这应该发生在认证尝试之前，因为Zend_Auth::authenticate()执行身份的自动存储。

// Save a reference to the Singleton instance of Zend_Auth
$auth = Zend_Auth::getInstance();

// Use 'someNamespace' instead of 'Zend_Auth'
$auth->setStorage(new Zend_Auth_Storage_Session('someNamespace'));

/**
 * @todo Set up the auth adapter, $authAdapter
 */

// Authenticate, saving the result, and persisting the identity on
// success
$result = $auth->authenticate($authAdapter);

实现订制存储

有时候开发者需要使用不同的身份持久行为，而不是Zend_Auth_Storage_Session提供的。对于这样的案例开发者可以简单地实现Zend_Auth_Storage_Interface并给Zend_Auth::setStorage()提供一个类的实例。

Example #2 使用定制存储类

为了使用不同于Zend_Auth_Storage_Session的身份之久存储类，开发者可实现Zend_Auth_Storage_Interface：

class MyStorage implements Zend_Auth_Storage_Interface
{
    /**
     * Returns true if and only if storage is empty
     *
     * @throws Zend_Auth_Storage_Exception If it is impossible to
     *                                     determine whether storage
     *                                     is empty
     * @return boolean
     */
    public function isEmpty()
    {
        /**
         * @todo implementation
         */
    }

    /**
     * Returns the contents of storage
     *
     * Behavior is undefined when storage is empty.
     *
     * @throws Zend_Auth_Storage_Exception If reading contents from
     *                                     storage is impossible
     * @return mixed
     */
    public function read()
    {
        /**
         * @todo implementation
         */
    }

    /**
     * Writes $contents to storage
     *
     * @param  mixed $contents
     * @throws Zend_Auth_Storage_Exception If writing $contents to
     *                                     storage is impossible
     * @return void
     */
    public function write($contents)
    {
        /**
         * @todo implementation
         */
    }

    /**
     * Clears contents from storage
     *
     * @throws Zend_Auth_Storage_Exception If clearing contents from
     *                                     storage is impossible
     * @return void
     */
    public function clear()
    {
        /**
         * @todo implementation
         */
    }
}

为了使用这个定制的存储类，在认证查询被尝试前，Zend_Auth::setStorage()被调用：

// Instruct Zend_Auth to use the custom storage class
Zend_Auth::getInstance()->setStorage(new MyStorage());

/**
 * @todo Set up the auth adapter, $authAdapter
 */

// Authenticate, saving the result, and persisting the identity on
// success
$result = Zend_Auth::getInstance()->authenticate($authAdapter);

使用Zend_Auth

这里提供了两种方法使用Zend_Auth适配器：

  1. 非直接地，通过Zend_Auth::authenticate()

  2. 直接地，通过适配器的 authenticate() 方法

下面的例子通过Zend_Auth类来示例如何非直接地使用Zend_Auth适配器：

// Get a reference to the singleton instance of Zend_Auth
require_once 'Zend/Auth.php';
$auth = Zend_Auth::getInstance();

// Set up the authentication adapter
$authAdapter = new MyAuthAdapter($username, $password);

// Attempt authentication, saving the result
$result = $auth->authenticate($authAdapter);

if (!$result->isValid()) {
    // Authentication failed; print the reasons why
    foreach ($result->getMessages() as $message) {
        echo "$message\n";
    }
} else {
    // Authentication succeeded; the identity ($username) is stored
    // in the session
    // $result->getIdentity() === $auth->getIdentity()
    // $result->getIdentity() === $username
}

一旦在一个请求里的认证被尝试，如上面的例子，检查一个成功的被认证的身份是否存在就是一个简单的匹配：

$auth = Zend_Auth::getInstance();
if ($auth->hasIdentity()) {
    // Identity exists; get it
    $identity = $auth->getIdentity();
}

从持久存储空间出去一个身份，可简单地使用clearIdentity()方法。这将被典型地用作“logout”操作。

Zend_Auth::getInstance()->clearIdentity();

当自动使用持久存储空间对特定的用例不合适，开发者可简单地忽略Zend_Auth类，直接使用适配器类。直接使用适配器类需要配置和准备适配器对象和调用它的authenticate()方法。适配器规范细节将在每个适配器的文档中讨论。下面的例子直接使用 MyAuthAdapter：

// Set up the authentication adapter
$authAdapter = new MyAuthAdapter($username, $password);

// Attempt authentication, saving the result
$result = $authAdapter->authenticate();

if (!$result->isValid()) {
    // Authentication failed; print the reasons why
    foreach ($result->getMessages() as $message) {
        echo "$message\n";
    }
} else {
    // Authentication succeeded
    // $result->getIdentity() === $username
}

Zend_Auth
Zend_Auth
Zend Framework手册 中文版
数据库表认证
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Auth
  • 简介
  • 数据库表认证
  • 摘要式认证
  • HTTP 认证适配器
  • LDAP 认证
  • Open ID Authentication


数据库表认证 - Zend Framework Manual

简介
Zend_Auth
Zend Framework手册 中文版
摘要式认证

数据库表认证

简介

Zend_Auth_Adapter_DbTable提供依靠存储在数据库表中的证书来认证的能力。因为Zend_Auth_Adapter_DbTable需要Zend_Db_Adapter_Abstract的实例来传递给它的构造器，所以每个实例要和特定的数据库连接绑定。其它配置选项可以通过构造器和实例方法设置，每个选项有一个配置。

可用的配置选项包括：

  • tableName: 包含认证证书的数据库表名，执行数据库认证查询需要依靠这个证书。

  • identityColumn: 数据库表的列的名称，用来表示身份。身份列必须包含唯一的值，例如用户名或者e-mail地址。

  • credentialColumn: 数据库表的列的名称，用来表示证书。在一个简单的身份和密码认证scheme下，证书的值对应为密码。参见 credentialTreatment 选项。

  • credentialTreatment: 在许多情况下，密码和其他敏感数据是加密的（encrypted, hashed, encoded, obscured,salted 或者通过以下函数或算法来加工）。通过指定参数化的字串来使用这个方法，例如'MD5(?)' 或者 'PASSWORD(?)'，开发者可以在输入证书数据时使用任意的SQL。因为这些函数对其下面的RDBMS是专用的， 请查看数据库手册来确保你所用的数据库的函数的可用性。

Example #1 基本用法

正如在简介中所解释的，Zend_Auth_Adapter_DbTable构造器需要一个Zend_Db_Adapter_Abstract的实例，这个实例用做数据库连结，并且认证适配器实例绑定到这个数据库连接。首先，应该创建数据库连接。

下面的代码为in-memory数据库创建一个适配器，创建一个简单的表schema，并插入我们将来可以执行认证查询的一行（数据）。这个例子需要PDO SQLite extension可用：

// 创建一个 in-memory SQLite 数据库连接
$dbAdapter = new Zend_Db_Adapter_Pdo_Sqlite(array('dbname' =>
                                                  ':memory:'));

// 构造一个简单表的创建语句
$sqlCreate = 'CREATE TABLE [users] ('
           . '[id] INTEGER  NOT NULL PRIMARY KEY, '
           . '[username] VARCHAR(50) UNIQUE NOT NULL, '
           . '[password] VARCHAR(32) NULL, '
           . '[real_name] VARCHAR(150) NULL)';

// 创建认证证书表
$dbAdapter->query($sqlCreate);

// 构造用来插入一行可以成功认证的数据的语句
$sqlInsert = "INSERT INTO users (username, password, real_name) "
           . "VALUES ('my_username', 'my_password', 'My Real Name')";

// 插入数据
$dbAdapter->query($sqlInsert);

随着数据库连接和表数据已经可用，Zend_Auth_Adapter_DbTable可以被创建。配置选项的值可以传递给构造器或者延后在实例化以后用做setter方法的参数:

// 用构造器参数来配置实例...
$authAdapter = new Zend_Auth_Adapter_DbTable(
    $dbAdapter,
    'users',
    'username',
    'password'
);

// 用构造器参数来配置实例...
$authAdapter = new Zend_Auth_Adapter_DbTable($dbAdapter);

$authAdapter
    ->setTableName('users')
    ->setIdentityColumn('username')
    ->setCredentialColumn('password')
;

在这点上，认证适配器实例已经可以接受认证查询。为了合成一个认证查询，在调用authenticate()方法之前，输入的证书的值要传递给适配器：

// 设置输入的证书的值（例如，从登陆的表单）
$authAdapter
    ->setIdentity('my_username')
    ->setCredential('my_password')
;

// 执行认证查询，并保存结果
$result = $authAdapter->authenticate();

除了基于认证结果对象的 getIdentity() 方法的可用性之外，Zend_Auth_Adapter_DbTable也支持从认证成功的表中读取一行数据：

// 输出身份
echo $result->getIdentity() . "\n\n";

// 输出结果行
print_r($authAdapter->getResultRowObject());

/* Output:
my_username

Array
(
    [id] => 1
    [username] => my_username
    [password] => my_password
    [real_name] => My Real Name
)
*/

因为表行里包含证书值，通过防止无意识地访问来安全化这个值很重要。

高级使用：持久一个 DbTable 结果对象

缺省地，基于成功的认证Zend_Auth_Adapter_DbTable 返回提供给auth对象的身份。对于其他用例情景，如开发者想给Zend_Auth 的持久存储机制存储一个包括其他有用信息的身份对象，已经通过使用getResultRowObject() 方法返回一个stdClass对象解决了。下面的代码片段举例说明它的用法：

// authenticate with Zend_Auth_Adapter_DbTable
$result = $this->_auth->authenticate($adapter);

if ($result->isValid()) {
    // store the identity as an object where only the username and
    //real_name have been returned
    $storage = $this->_auth->getStorage();
    $storage->write($adapter->getResultRowObject(array(
        'username',
        'real_name',
    )));

    // store the identity as an object where the password column has
    // been omitted
    $storage->write($adapter->getResultRowObject(
        null,
        'password'
    ));

    /* ... */

} else {

    /* ... */

}

高级用法范例

虽然 Zend_Auth （和它的继承者 Zend_Auth_Adapter_DbTable ）主要用来 认证 而不是 授权 ，但是基于它们用在哪个域名下，还是有一些实例和问题。根据如何解释你的问题，有时候通过在认证适配器里检查授权问题也许能解决问题。

用一点不恰当的免责声明，Zend_Auth_Adapter_DbTable 有内建的机制可以用来利用添加另外的认证时的检查来解决一些普通的用户问题。

// The status field value of an account is not equal to "compromised"
$adapter = new Zend_Auth_Adapter_DbTable(
    $db,
    'users',
    'username',
    'password',
    'MD5(?) AND status != "compromised"'
);

// The active field value of an account is equal to "TRUE"
$adapter = new Zend_Auth_Adapter_DbTable(
    $db,
    'users',
    'username',
    'password',
    'MD5(?) AND active = "TRUE"'
);

另外一个场景是免疫机制的实现。免疫是指大幅提高程序安全的技术术语。 它的想法是基于连接随机字符串到每个密码来使从字典里预先计算好的哈希值来完成强力攻击数据库成为可能。

因此我们需要修改表来存储免疫的字符串：

$sqlAlter = "ALTER TABLE [users] "
          . "ADD COLUMN [password_salt] "
          . "AFTER [password]";

$dbAdapter->query($sqlAlter);

这里是在注册时给每个用户生成免疫字符串的简单的方法：

for ($i = 0; $i < 50; $i++)
{
    $dynamicSalt .= chr(rand(33, 126));
}

构造适配器：

$adapter = new Zend_Auth_Adapter_DbTable(
    $db,
    'users',
    'username',
    'password',
    "MD5(CONCAT('"
    . Zend_Registry::get('staticSalt')
    . "', ?, password_salt))"
);

Note: 你可以通过使用静态免疫值硬编码到程序里来更好地改善安全问题。 万一你的数据库有安全隐患（例如 SQL 注入攻击），但你的 web 服务器 依然完整，攻击者仍得不到你的数据。

简介
Zend_Auth
Zend Framework手册 中文版
摘要式认证
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Auth
  • 简介
  • 数据库表认证
  • 摘要式认证
  • HTTP 认证适配器
  • LDAP 认证
  • Open ID Authentication


摘要式认证 - Zend Framework Manual

数据库表认证
Zend_Auth
Zend Framework手册 中文版
HTTP 认证适配器

摘要式认证

简介

» 摘要式认证是一个HTTP认证的方法，它通过不需要通过网络传递明文密码的方法对» 基本认证加以改进。

这个适配器允许依靠文本文件认证，该文本包括数行摘要式认证的基本元素：

  • 用户名，例如 "joe.user"

  • 领域，例如 "Administrative Area"

  • 用户名，领域和密码的MD5 hash用冒号隔开

在下面的例子中，上面的元素用冒号隔开（密码是"somePassword"）：

someUser:Some Realm:fde17b91c3a510ecbaf7dbd37f59d4f8

规范（Specifics）

摘要式认证适配器Zend_Auth_Adapter_Digest需要若干输入参数：

  • 文件名 － 认证查询被执行是所需的文件名

  • 领域 － 摘要式认证领域

  • 用户名 － 摘要式认证用户

  • 密码 － 该领域用户的密码

在调用authenticate()之前必需要设定这些参数。

身份（Identity）

摘要式认证返回一个Zend_Auth_Result 对象，它由包含realm和username健值的数组的身份形成。在authenticate()被调用之前，分别设置和这些健值关联的数组值为相符的值。

<
$adapter = new Zend_Auth_Adapter_Digest($filename,
                                        $realm,
                                        $username,
                                        $password);

$result = $adapter->authenticate();

$identity = $result->getIdentity();

print_r($identity);

/*
Array
(
    [realm] => Some Realm
    [username] => someUser
)
*/
数据库表认证
Zend_Auth
Zend Framework手册 中文版
HTTP 认证适配器
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Auth
  • 简介
  • 数据库表认证
  • 摘要式认证
  • HTTP 认证适配器
  • LDAP 认证
  • Open ID Authentication


HTTP 认证适配器 - Zend Framework Manual

摘要式认证
Zend_Auth
Zend Framework手册 中文版
LDAP 认证

HTTP 认证适配器

简介

Zend_Auth_Adapter_Http提供一个大部分符合» RFC-2617的» 基本 和 » 摘要 HTTP 认证。摘要认证是一个认证的方法，它在基本认证的基础上做了改进，不需要在网络上传输明文密码。

主要特性：

  • 支持基本和摘要认证。

  • 对所有支持的 schemes 发出请求，所以客户端可以响应任何它所支持的 scheme。

  • 支持代理认证。

  • 包括支持文本文件认证和提供一个接口来支持其它资源认证，例如数据库。

还有一些显著的 RFC-2617 特性没有实现：

  • Nonce 跟踪，它将考虑 "stale" 支持，和增强的重放供给保护。

  • 带完整性检查的认证，或 "auth-int"。

  • HTTP 认证信息头。

设计回顾

这个适配器包括两个子组件，HTTP authentication类本身和所谓的 "Resolvers"。HTTP authentication类封装了实现基本和摘要认证的逻辑。它使用Resolver在数据存储（缺省是文本文件）中查找客户的身份并取出证书。"resolved" 的证书和客户的输入相比较来决定认证是否成功。

配置选项

Zend_Auth_Adapter_Http 类需要一个配置数组传递给它的构造器。有若干个配置选项有效，其中一些是必需的：

配置选项
选项名称 | 是否必须 | 描述
accept_schemes | 是 | 决定适配器从客户端接受哪个认证schemes。必须是包括'basic' 和/或 'digest'的空格分隔的列表。
realm | 是 | 设置认证领域；在给定的领域里用户名必须是唯一的。
digest_domains | 是，当'accept_schemes' 包含 'digest' | 相同认证信息是有效的空格分隔的URIs列表。 URIs不需要都只想同一个服务器。
nonce_timeout | 是，当'accept_schemes' 包含 'digest' | 设置nonce有效的秒数。参见下面的注解。
proxy_auth | 否 | 缺省是 Disabled 。Enable 后执行代理认证而不是正常的源服务器认证。

Note: 当前的nonce_timeout实现有一些有趣的副作用。这个设置用来决定给定的nonce的有效寿命，或者客户端的认证信息多长时间被有效地接受。目前，如果它被设置为3600（例如），它将导致适配器准点地每个小时提示客户端提供新的证书。一旦nonce跟踪和stale支持实现，这在将来的版本中被解决。

Resolvers

Resolver的作用是接受用户名和领域，并返回证书值。基本认证期望接收用户密码的Base64编码版本。摘要认证期望接收用户的用户名，领域和密码（用冒号分隔）的hash。当前，唯一支持的hash算法是MD5。

Zend_Auth_Adapter_Http 依靠对象实现 Zend_Auth_Adapter_Http_Resolver_Interface。适配器中包含一个文本文件resolver类，但任何其它种类的resolver可以通过实现resolver接口来创建。

文件 Resolver

文件resolver是一个非常简单的类。它有一个单个的属性指定一个文件名，它也可以被传递给构造器。它的resolve()方法遍历文本文件，用匹配用户名和领域来搜索一行。文本文件的格式和Apache htpasswd文件类似：

<username>:<realm>:<credentials>\n
每行包含三个字段 - 用户名，领域 和 证书 - 用冒号分隔。证书字段对文件resolver不透明；它被简单地不做修改地返回给调用者。所以，这同样的文件格式对基本和摘要认证都适合。对基本认证，证书字段应该是Base64编码的用户的密码。对摘要认证，它应该是上述的MD5 hash。

有两个同等简单的方法创建文件 Resolver:

$path     = 'files/passwd.txt';
$resolver = new Zend_Auth_Adapter_Http_Resolver_File($path);
或者
$path     = 'files/passwd.txt';
$resolver = new Zend_Auth_Adapter_Http_Resolver_File();
$resolver->setFile($path);
如果给定的路径是空的或不可读，将抛出一个异常。

基本用法

首先，建立一个带有必需的配置值得数组：

$config = array(
    'accept_schemes' => 'basic digest',
    'realm'          => 'My Web Site',
    'digest_domains' => '/members_only /my_account',
    'nonce_timeout'  => 3600,
);
这个数组将使适配器接收基本或者摘要认证，并将请求对所有在/members_only 和/my_account之下的区域认证访问。领域值通常在浏览器中密码对话框中显示。nonce_timeout，当然，会有上述的行为。

下一步, 创建 Zend_Auth_Adapter_Http 对象：

$adapter = new Zend_Auth_Adapter_Http($config);

因为我们对基本和摘要认证都支持，所以我们需要两个不同的resolver对象。注意这仅仅简单地是两个不同的类：

$basicResolver = new Zend_Auth_Adapter_Http_Resolver_File();
$basicResolver->setFile('files/basicPasswd.txt');

$digestResolver = new Zend_Auth_Adapter_Http_Resolver_File();
$digestResolver->setFile('files/digestPasswd.txt');

$adapter->setBasicResolver($basicResolver);
$adapter->setDigestResolver($digestResolver);

最后，我们执行认证。为了完成认证，适配器对请求（Request）和响应（Response）都需要一个reference：

assert($request instanceof Zend_Controller_Request_Http);
assert($response instanceof Zend_Controller_Response_Http);

$adapter->setRequest($request);
$adapter->setResponse($response);

$result = $adapter->authenticate();
if (!$result->isValid()) {
    // 错误的 userame/password，或者取消了密码提示
}

摘要式认证
Zend_Auth
Zend Framework手册 中文版
LDAP 认证
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Auth
  • 简介
  • 数据库表认证
  • 摘要式认证
  • HTTP 认证适配器
  • LDAP 认证
  • Open ID Authentication


LDAP 认证 - Zend Framework Manual

HTTP 认证适配器
Zend_Auth
Zend Framework手册 中文版
Open ID Authentication

LDAP 认证

简介

Zend_Auth_Adapter_Ldap 用 LDAP 服务支持 web 程序认证。它的功能包括用户名和域名规范化、多域认证和实效切（failover）换能力。经测试，它能与 » Microsoft Active Directory 和 » OpenLDAP 一起工作，它也应该能和其它 LDAP 服务提供者一起工作。

本文档包括使用 Zend_Auth_Adapter_Ldap 的指南、它的 API 、各种可用选项的大纲、认证问题故障排除的诊断信息和Active Directory 与 OpenLDAP 服务器的范例选项。

用法

为了快速把 Zend_Auth_Adapter_Ldap 认证集成到你的程序中，即使你不使用 Zend_Controller，代码的基本部分看起来是这样的：

$username = $this->_request->getParam('username');
$password = $this->_request->getParam('password');

$auth = Zend_Auth::getInstance();

$config = new Zend_Config_Ini('../application/config/config.ini',
                              'production');
$log_path = $config->ldap->log_path;
$options = $config->ldap->toArray();
unset($options['log_path']);

$adapter = new Zend_Auth_Adapter_Ldap($options, $username,
                                      $password);

$result = $auth->authenticate($adapter);

if ($log_path) {
    $messages = $result->getMessages();

    $logger = new Zend_Log();
    $logger->addWriter(new Zend_Log_Writer_Stream($log_path));
    $filter = new Zend_Log_Filter_Priority(Zend_Log::DEBUG);
    $logger->addFilter($filter);

    foreach ($messages as $i => $message) {
        if ($i-- > 1) { // $messages[2] and up are log messages
            $message = str_replace("\n", "\n  ", $message);
            $logger->log("Ldap: $i: $message", Zend_Log::DEBUG);
        }
    }
}
虽然日志（ logging ）代码是可选的，还是强烈建议使用日志。Zend_Auth_Adapter_Ldap 将记录任何想要的信息细节到 $messages （更多的信息看下面），对于难以调试的程序来说，有历史记录这是个很好的功能。

上面用到 Zend_Config_Ini 的代码是来加载适配器选项，它也是可选的，使用一个规则的数组来完成工作。下面是带有两个单独的服务器选项的 application/config/config.ini 文件的例子。带有多组服务器选项的适配器将按顺序来尝试每个服务器直到资格被成功认证。服务器的名字 （例如 server1 and server2）是任意的，关于选项数组的细节，参见下面 Server Options 一节。 注意 Zend_Config_Ini 要求任何带有等号（=）的值需要括起来（如下面的 DNs）。

[production]

ldap.log_path = /tmp/ldap.log

; Typical options for OpenLDAP
ldap.server1.host = s0.foo.net
ldap.server1.accountDomainName = foo.net
ldap.server1.accountDomainNameShort = FOO
ldap.server1.accountCanonicalForm = 3
ldap.server1.username = "CN=user1,DC=foo,DC=net"
ldap.server1.password = pass1
ldap.server1.baseDn = "OU=Sales,DC=foo,DC=net"
ldap.server1.bindRequiresDn = true

; Typical options for Active Directory
ldap.server2.host = dc1.w.net
ldap.server2.useSsl = true
ldap.server2.accountDomainName = w.net
ldap.server2.accountDomainNameShort = W
ldap.server2.accountCanonicalForm = 3
ldap.server2.baseDn = "CN=Users,DC=w,DC=net"
上述的配置将指示 Zend_Auth_Adapter_Ldap 首先来尝试用 OpenLDAP 服务器 s0.foo.net 来认证用户，如果不论什么原因认证失败，将尝试 AD 服务器 dc1.w.net。

这个配置示例了在不同的域的服务器的多域认证，也可以在同一域中用多个服务器来提供冗余。

注意在这个例子中，即使 OpenLDAP 不需要用于 Windows 的短 NetBIOS 风格的域名，我们仍在这里提供它以保证命名正规化 （参见下面的 Username Canonicalization 一节）。

The API

Zend_Auth_Adapter_Ldap 构造器接受三个参数。

$options 参数是必需的并且是一个包含一组或多组选项的数组。注意它是 Zend_Ldap 选项的 数组的数组 。即使你只使用一个 LDAP 服务器，选项仍要包含在另一个数组中。

下面是一个选项参数包含两组服务器选项（ s0.foo.net 和 dc1.w.net （和上面 INI 表示法一样的选项））的例子的 » print_r() 输出：

Array
(
    [server2] => Array
        (
            [host] => dc1.w.net
            [useSsl] => 1
            [accountDomainName] => w.net
            [accountDomainNameShort] => W
            [accountCanonicalForm] => 3
            [baseDn] => CN=Users,DC=w,DC=net
        )

    [server1] => Array
        (
            [host] => s0.foo.net
            [accountDomainName] => foo.net
            [accountDomainNameShort] => FOO
            [accountCanonicalForm] => 3
            [username] => CN=user1,DC=foo,DC=net
            [password] => pass1
            [baseDn] => OU=Sales,DC=foo,DC=net
            [bindRequiresDn] => 1
        )

)
上述每组选项提供的信息是不同的，主要是因为当绑定（参见下面 服务器选项 一节中的 bindRequiresDn 选项）时 AD 不要求在 DN 表单中的有用户名，这意味着我们可以忽略很多和为认证用户名获取 DN 相关的选项。

Note: 什么是 DN?
 DN 或者 "distinguished name" 是一个字符串，表示在 LDAP 目录中到一个对象的路径。每个用逗号分隔的组件是一个属性并且它的值表示一个节点。组件是按反顺序来算的，例如：用户账户 CN=Bob Carter,CN=Users,DC=w,DC=net 直接位于 CN=Users,DC=w,DC=net container 里的。这种结构用 LDAP 浏览器如 ADSI Edit MMC snap-in for Active Directory 或 phpLDAPadmin 可以最好地浏览。

服务器名（如上面的 'server1' 和 'server2'）是任意的，但因为使用 Zend_Config，标识符（identifiers）应当以数字索引的相反出现并且不应当包含任何用于相关文件格式（例如，'.' INI 属性分隔符，XML 条目参考 '&' 等）的特殊字符。

用多组服务器选项，适配器可以在多域的环境中认证用户并提供 failover （估计是失败后尝试下一个服务器），所以如果一个服务器不可用，将查询另一个。

Note: 非常详细的介绍 （The Gory Details）－ 在认证方法中到底发生了什么？
 当调用 authenticate() 方法，适配器反复把每组服务器选项设置到内部 Zend_Ldap 实例并带用于认证的用户名和密码调用 Zend_Ldap::bind() 方法。Zend_Ldap 类检查用户名是否在域中合格 （例如，有域的组件如 alice@foo.net 或 FOO\alice）。如果域存在，但它不匹配任何一种服务器的域名（foo.net 或 FOO），就抛出一个特殊的异常并由 Zend_Auth_Adapter_Ldap 捕捉，这样那个服务器就被忽略并且选择下个服务器选项。如果域名 确实 匹配，但是如果用户没有提供一个合格的用户名，Zend_Ldap 继续尝试绑定被提供的证书（credentials）。如果绑定不成功，Zend_Ldap 抛出一个由 Zend_Auth_Adapter_Ldap 捕捉的 Zend_Ldap_Exception 并尝试下一组服务器选项。如果绑定成功，反复尝试（迭代？(iteration)）就停止，并且适配器的 authenticate() 方法返回一个成功的结果。如果所有服务器选项都试过了而且都不成功，认证就失败了，authenticate() 返回一个失败的结果并带有最后一个尝试的错误消息。

Zend_Auth_Adapter_Ldap 构造器的用户名和密码参数是要被认证的证书（例如，用户通过 HTML 登录表单提供的证书（credentials））。另外，也可以通过 setUsername() 和 setPassword() 方法来设置。

服务器选项

在 Zend_Auth_Adapter_Ldap 的上下文中 的每组服务器选项包含下列选项，它们基本上不可修改地传递给 Zend_Ldap::setOptions()：

服务器选项
名称 | 描述
host | 这些选项表示的 LDAP 服务器的主机名，该选项是必需的。
port | LDAP 服务器监听的端口，如果 useSsl 是 true，缺省 端口 值是 636。如果 useSsl 是 false，缺省 端口 值是 389。
useSsl | 如果是 true，表示 LDAP 客户端应当使用 SSL / TLS 加密传输。在生产环境中强烈建议使用 true 值以防止明文传输密码。缺省值为 false 是因为服务器经常在安装之后请求被分别安装的证书。它也改变缺省 端口 值（ 见上面 端口 的描述）。
username | 账户的 DN， 用来执行账户 DN 查找。LDAP servers that require the username to be in DN form when performing the "bind" require this option （这句没有理解）。 如果 bindRequiresDn 是 true，这个选项是必需的。这个账户不需要是优先账户 － a account with read-only access to objects under the baseDn is all that is necessary (and preferred based on the Principle of Least Privilege).
password | 账户的密码，用来执行账户 DN 查找。如果没有提供这个选项，当执行账户 DN 查找时，LDAP 客户端将尝试“匿名绑定”。
bindRequiresDn | 一些 LDAP 服务器要求用户名以 DN 格式来绑定，如 CN=Alice Baker,OU=Sales,DC=foo,DC=net （基本上 除了 AD 以外所有的服务器）。如果这个选项是 true，Zend_Ldap 自动获取被认证的用户所对应的 DN。如果它不是 DN 格式，那就重新绑定合适的 DN。缺省值是 false。目前，当绑定时，只有微软的 Active Directory 服务器（ADS） 不 要求用户名为 DN 格式，所以和 AD 一起使用，这个选项可以是 false （而且应当是，因为获取 DN 需要额外的过程（round trip）到服务器），否则，这个选项必需设置为 true （例如，OpenLDAP）。当搜索账户时，这个选项也控制缺省的 acountFilterFormat，参见 accountFilterFormat 选项。
baseDn | 定位所有被认证账户下的 DN，这个选项是必需的。如果你不能确定正确的 baseDn 值，可以用 DC= 组件从用户的 DNS 域来产生它，例如，如果用户的基本名是 alice@foo.net，DC=foo,DC=net 的 baseDn 应当工作。然而更精确的位置（例如 OU=Sales,DC=foo,DC=net ）将更有效。
accountCanonicalForm | 一个是 2、3 或 4 的值，用来指示那个账户名在成功认证后需要规范化。值的解释具体如下：2 表示传统的用户名（例如 alice ），3 表示反斜杠式（backslash-style）名称（例如 FOO\alice），或者 4 表示基本式用户名（例如 alice@foo.net）。缺省值为 4 （例如 alice@foo.net ）。例如，当值为 3，由 Zend_Auth_Result::getIdentity() （如果使用了 Zend_Auth，则是 Zend_Auth::getIdentity()，） 返回的身份（identity）将总是 FOO\alice，不论 Alice 提供了什么格式，如 alice、 alice@foo.net、 FOO\alice、FoO\aLicE、 foo.net\alice 等。见 Zend_Ldap 中的 Account Name Canonicalization 一节有更多的细节。注意当使用多组服务器选项时，建议但不要求所有服务器选项使用相同的 accountCanonicalForm，这样，用户名对于同一格式总是规范化的（例如，对于 AD 服务器规范化为 EXAMPLE\username，但对于 OpenLDAP 服务器规范化为 username@example.com，对于程序的高水平（high-level）逻辑，这可能很不好用。）
accountDomainName | 目标 LDAP 服务器的 FQDN 域名是一个授权（authority）（例如 example.com）。该选项用来规范化名字，这样用户提供的用户名可以为绑定按需转换。它也可用来决定是否服务器对用户名是一个授权（例如 accountDomainName 是 foo.net 并且用户提供了 bob@bar.net，将不查询服务器并导致一个错误）。该选项不是必需的，但如果不提供，那就不支持用户名为基本名（principal name）格式（例如 alice@foo.net）。强烈建议使用该选项，因为许多用例要求生成基本名格式。
accountDomainNameShort | 目标 LDAP 服务器的 ‘短’ 域名是一个授权（authority）（例如 FOO）。注意按 1:1 来映射 accountDomainName 和 accountDomainNameShort。该选项用于为 Windows 网络指定 NetBIOS 名但也可用于非 AD 服务器（例如，当多组服务器选用使用反斜杠风格的 accountCanonicalForm时为了保持一致性）。该选项不是必需的但如果不使用，就不支持反斜杠格式的用户名（例如 FOO\alice）。
accountFilterFormat | 用来搜索账户的 LDAP 搜索过滤器。这个字符串是个 » printf() 风格的表达式，必需包含一个 '%s' 来适合用户名。缺省值为 '(&(objectClass=user)(sAMAccountName=%s))'，除非 bindRequiresDn 设置为 true，那样缺省值就是 '(&(objectClass=posixAccount)(uid=%s))'。例如，如果因为某种原因你想对 AD 使用 bindRequiresDn = true ，需要设置 accountFilterFormat = '(&(objectClass=user)(sAMAccountName=%s))'。

Note: 如果你设置 useSsl = true 可能发现 LDAP 客户端会产生一个不能校验服务器证书的错误。假定 PHP LDAP 扩展完全链接到 OpenLDAP 客户库，为解决这个问题你可以在 OpenLDAP 客户 ldap.conf 里设置 “TLS_REQCERT never” （并重启 web 服务器）来指明 OpenLDAP 客户端库你信任这个服务器。另外如果涉及到服务器可能被欺骗，你可以输出 LDAP 服务器的根证书并把它放到 web 服务器，这样 OpenLDAP 客户端可以校验服务器的身份。

收集调试信息

Zend_Auth_Adapter_Ldap 在它的 authenticate() 方法里收集调试信息。这个信息存储在 Zend_Auth_Result 对象里。下面描述由 Zend_Auth_Result::getMessages() 返回的数组：

调试信息 （Messages）
信息（Messages） 数组索引 | 描述
Index 0 | 显示给用户的用户友好的一般信息（例如无效的证书（credentials））。如果认证成功，这个字符串是空的。
Index 1 | 更详细的错误信息，不适合显示给用户但作为服务器操错日志。如果认证成功，这个字符串是空的。
Indexes 2 and higher | 所有日志信息按顺序从 index 2 开始。
实践上，index 0 显示给用户（例如使用 FlashMessenger 助手）， index 1 作为日志，如果收集到调试信息， index 2 和它以后的 index 也作为日志（尽管最终的信息总是从 index 1 的字符串开始）。

特定服务器的通用选项

Active Directory 的选项

对于 ADS，下列选项值得注意：

Active Directory 的选项
名字 | 另外的注释
host | 适用所有的服务器，该选项必需。
useSsl | 因为安全的缘故，如果服务器安装了必要的证书，这个应该是 true。
baseDn | 适用所有的服务器，该选项必需。缺省地 AD 把所有用户账户放在 Users 容器中 （例如 CN=Users,DC=foo,DC=net），但在大型组织里缺省不常见，要询问 AD 管理员你的程序账户的最好的 DN 是什么。
accountCanonicalForm | 几乎可以确定你想要这个值为 3 来使用反斜杠式的名称（例如 FOO\alice），这对于 Windows 用户来说是最熟悉的。你 不 应该使用不合格的格式 2 （例如 alice），因为它可能授权在其它信任域里（例如 BAR\alice 和 FOO\alice 将被当作相同的用户）相同名字的用户访问你的程序。（参见下面的注释）
accountDomainName | 使用 AD 时这是必需的除非使用 accountCanonicalForm 2 ，再强调一下，我们不鼓励这样用。
accountDomainNameShort | AD 服务器是授权的域用户的 NetBIOS 名称。如果使用反斜杠风格 accountCanonicalForm，这个是必需的。

Note: 从技术角度讲，用当前的 Zend_Auth_Adapter_Ldap 实现进行跨域认证是没有危险的，因为服务器域是被显式检查的，但对将来的实现未必是对的，如在运行时发现域名或者如果使用替代的适配器（例如 Kerberos）。一般来说，含糊的账户名是安全问题的来源，所以最好使用合格的账户名称。

OpenLDAP 的选项

对于 OpenLDAP 或一般的使用典型的 posixAccount 风格的 LDAP 服务器，下面的选项值得注意：

OpenLDAP 的选项
名字 | 另外的注释
host | 适用所有的服务器，该选项必需。
useSsl | 因为安全的缘故，如果服务器安装了必要的证书，这个应该是 true。
username | 必需并一定是一个 DN，因为当执行绑定时 OpenLDAP 要求 DN 格式的用户名。设法使用无特权的账户。
password | 对应上述用户名的密码，如果 LDAP 服务器支持匿名绑定，这个也许会忽略。
bindRequiresDn | 必需并一定是 true，因为当执行绑定时 OpenLDAP 要求 DN 格式的用户名。
baseDn | 适用所有的服务器，该选项是必需的并指示所有被认证的账户的 DN 的定位。
accountCanonicalForm | 可选但缺省值是 4 （基本风格名如 alice@foo.net），如果适用反斜杠式的名字（如 FOO\alice）这个也许不是理想的。对于反斜杠式名字值为 3。
accountDomainName | 必需，除非使用不推荐的 accountCanonicalForm 2，
accountDomainNameShort | 如果不使用 AD ，这个值不是必需的。否则，如果使用 accountCanonicalForm 3 ，该选项必需并是个完全对应 accountDomainName 的短名 （例如如果 accountDomainName 是 foo.net，一个好的 accountDomainNameShort 值可能是 FOO）。

HTTP 认证适配器
Zend_Auth
Zend Framework手册 中文版
Open ID Authentication
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Auth
  • 简介
  • 数据库表认证
  • 摘要式认证
  • HTTP 认证适配器
  • LDAP 认证
  • Open ID Authentication


Open ID Authentication - Zend Framework Manual

LDAP 认证
Zend_Auth
Zend Framework手册 中文版
Zend_Barcode

Open ID Authentication

简介

Zend_Auth_Adapter_OpenId 允许认证用户使用远程 OpenID 服务器，这样的认证过程假设用户只提交他们的 OpenID 身份给 web 程序，接着他们被重定向到 OpenID 的提供者通过密码或其它办法来验证身份，本地的 web 程序是永远不会知道密码的。

OpenID 身份只是个指向一些 web 页面的 HTTP URL，在 URL 中带有适当的用户和特别标签的信息，在标签中描述使用哪个服务器和提交哪个身份到那里。关于 OpenID 请参考 » OpenID 官方网站 .

Zend_Auth_Adapter_OpenId 类是 Zend_OpenId_Consumer 组件的封装，而 >Zend_OpenId_Consumer 组件实现 OpenID 认证协议自己。

Note: Zend_OpenId 利用有效的 » GMP extension。当使用 Zend_Auth_Adapter_OpenId 时，可以考虑打开 GMP extension 来改善性能。

细节

作为 Zend_Auth 的适配器，Zend_Auth_Adapter_OpenId 类实现了 Zend_Auth_Adapter_Interface，而Zend_Auth_Adapter_Interface 定义了一个方法 － authenticate()。这个方法执行认证，但在调用之前要准备号对象，适配器准备包括设置 OpenID 身份和其它 Zend_OpenId 特殊选项。

然而和其它 Zend_Auth 的适配器不同，它在外部服务器上执行认证并在两次分开的 HTTP 请求中完成，所以必须调用 Zend_Auth_Adapter_OpenId::authenticate() 两次。第一次这个方法不返回，但重定向用户到他们的 OpenID 服务器，然后在服务器上认证后又重定向回来，第二次请求的脚本必须再调用 Zend_Auth_Adapter_OpenId::authenticate() 来校验从服务器返回的重定向请求带来的签名，然后完成认证处理，最后，这个方法将返回期望的 Zend_Auth_Result 对象。

下面的例子展示 Zend_Auth_Adapter_OpenId 的用法。正如前面所说，Zend_Auth_Adapter_OpenId::authenticate() 被调用两次。第一次 － 在提交 HTML 表单之后，当 $_POST['openid_action'] 设置给 "login"时；第二次 － 在从 OpenID 服务器重定向 HTTP 之后，当 $_GET['openid_mode'] 或 $_POST['openid_mode'] 被设置。

<?php
$status = "";
$auth = Zend_Auth::getInstance();
if ((isset($_POST['openid_action']) &&
     $_POST['openid_action'] == "login" &&
     !empty($_POST['openid_identifier'])) ||
    isset($_GET['openid_mode']) ||
    isset($_POST['openid_mode'])) {
    $result = $auth->authenticate(
        new Zend_Auth_Adapter_OpenId(@$_POST['openid_identifier']));
    if ($result->isValid()) {
        $status = "You are logged in as "
                . $auth->getIdentity()
                . "<br>\n";
    } else {
        $auth->clearIdentity();
        foreach ($result->getMessages() as $message) {
            $status .= "$message<br>\n";
        }
    }
} else if ($auth->hasIdentity()) {
    if (isset($_POST['openid_action']) &&
        $_POST['openid_action'] == "logout") {
        $auth->clearIdentity();
    } else {
        $status = "You are logged in as "
                . $auth->getIdentity()
                . "<br>\n";
    }
}
?>
<html><body>
<?php echo htmlspecialchars($status);?>
<form method="post"><fieldset>
<legend>OpenID Login</legend>
<input type="text" name="openid_identifier" value="">
<input type="submit" name="openid_action" value="login">
<input type="submit" name="openid_action" value="logout">
</fieldset></form></body></html>
*/

允许和下面这些方法一起来定制 OpenID 认证过程：从 OpenID 服务器上接收在分开的页面上的重定向；指定网站的 "root"。在这种情况下，使用 Zend_OpenId_Consumer_Storage 或 Zend_Controller_Response。也可以使用注册扩展（Registration Extension）来从 OpenID 服务器上获取用户信息。所有这些可能性在 Zend_OpenId_Consumer 有详细描述。

LDAP 认证
Zend_Auth
Zend Framework手册 中文版
Zend_Barcode
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Auth
  • 简介
  • 数据库表认证
  • 摘要式认证
  • HTTP 认证适配器
  • LDAP 认证
  • Open ID Authentication


Zend_Barcode - Zend Framework Manual

Open ID Authentication
Zend Framework Reference
Zend Framework手册 中文版
Introduction

Zend_Barcode

Table of Contents
  • Introduction
  • Barcode creation using Zend_Barcode class
  • Zend_Barcode Objects
  • Zend_Barcode Renderers
Open ID Authentication
Zend Framework Reference
Zend Framework手册 中文版
Introduction
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


Introduction - Zend Framework Manual

Zend_Barcode
Zend_Barcode
Zend Framework手册 中文版
Barcode creation using Zend_Barcode class

Introduction

Zend_Barcode provides a generic way to generate barcodes. The Zend_Barcode component is divided into two subcomponents: barcode objects and renderers. Objects allow you to create barcodes independently of the renderer. Renderer allow you to draw barcodes based on the support required.

Zend_Barcode
Zend_Barcode
Zend Framework手册 中文版
Barcode creation using Zend_Barcode class
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Barcode
  • Introduction
  • Barcode creation using Zend_Barcode class
  • Zend_Barcode Objects
  • Zend_Barcode Renderers


Barcode creation using Zend_Barcode class - Zend Framework Manual

Introduction
Zend_Barcode
Zend Framework手册 中文版
Zend_Barcode Objects

Barcode creation using Zend_Barcode class

Using Zend_Barcode::factory

Zend_Barcode uses a factory method to create an instance of a renderer that extends Zend_Barcode_Renderer_RendererAbstract. The factory method accepts five arguments.

  1. The name of the barcode format (e.g., "code39") (required)

  2. The name of the renderer (e.g., "image") (required)

  3. Options to pass to the barcode object (an array or Zend_Config object) (optional)

  4. Options to pass to the renderer object (an array or Zend_Config object) (optional)

  5. Boolean to indicate whether or not to automatically render errors. If an exception occurs, the provided barcode object will be replaced with an Error representation (optional default TRUE)

Example #1 Getting a Renderer with Zend_Barcode::factory()

Zend_Barcode::factory() instantiates barcode objects and renderers and ties them together. In this first example, we will use the Code39 barcode type together with the Image renderer.

  1. // Only the text to draw is required
  2. $barcodeOptions = array('text' => 'ZEND-FRAMEWORK');
  3.
  4. // No required options
  5. $rendererOptions = array();
  6. $renderer = Zend_Barcode::factory(
  7.     'code39', 'image', $barcodeOptions, $rendererOptions
  8. );

Example #2 Using Zend_Barcode::factory() with Zend_Config objects

You may pass a Zend_Config object to the factory in order to create the necessary objects. The following example is functionally equivalent to the previous.

  1. // Using only one Zend_Config object
  2. $config = new Zend_Config(array(
  3.     'barcode'        => 'code39',
  4.     'barcodeParams'  => array('text' => 'ZEND-FRAMEWORK'),
  5.     'renderer'       => 'image',
  6.     'rendererParams' => array('imageType' => 'gif'),
  7. ));
  8.
  9. $renderer = Zend_Barcode::factory($config);

Drawing a barcode

When you draw the barcode, you retrieve the resource in which the barcode is drawn. To draw a barcode, you can call the draw() of the renderer, or simply use the proxy method provided by Zend_Barcode.

Example #3 Drawing a barcode with the renderer object

  1. // Only the text to draw is required
  2. $barcodeOptions = array('text' => 'ZEND-FRAMEWORK');
  3.
  4. // No required options
  5. $rendererOptions = array();
  6.
  7. // Draw the barcode in a new image,
  8. $imageResource = Zend_Barcode::factory(
  9.     'code39', 'image', $barcodeOptions, $rendererOptions
  10. )->draw();

Example #4 Drawing a barcode with Zend_Barcode::draw()

  1. // Only the text to draw is required
  2. $barcodeOptions = array('text' => 'ZEND-FRAMEWORK');
  3.
  4. // No required options
  5. $rendererOptions = array();
  6.
  7. // Draw the barcode in a new image,
  8. $imageResource = Zend_Barcode::draw(
  9.     'code39', 'image', $barcodeOptions, $rendererOptions
  10. );

Renderering a barcode

When you render a barcode, you draw the barcode, you send the headers and you send the resource (e.g. to a browser). To render a barcode, you can call the render() method of the renderer or simply use the proxy method provided by Zend_Barcode.

Example #5 Renderering a barcode with the renderer object

  1. // Only the text to draw is required
  2. $barcodeOptions = array('text' => 'ZEND-FRAMEWORK');
  3.
  4. // No required options
  5. $rendererOptions = array();
  6.
  7. // Draw the barcode in a new image,
  8. // send the headers and the image
  9. Zend_Barcode::factory(
  10.     'code39', 'image', $barcodeOptions, $rendererOptions
  11. )->render();

This will generate this barcode:

< class="inlinemediaobject">

Example #6 Renderering a barcode with Zend_Barcode::render()

  1. // Only the text to draw is required
  2. $barcodeOptions = array('text' => 'ZEND-FRAMEWORK');
  3.
  4. // No required options
  5. $rendererOptions = array();
  6.
  7. // Draw the barcode in a new image,
  8. // send the headers and the image
  9. Zend_Barcode::render(
  10.     'code39', 'image', $barcodeOptions, $rendererOptions
  11. );

This will generate the same barcode as the previous example.

Introduction
Zend_Barcode
Zend Framework手册 中文版
Zend_Barcode Objects
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Barcode
  • Introduction
  • Barcode creation using Zend_Barcode class
  • Zend_Barcode Objects
  • Zend_Barcode Renderers


Zend_Barcode Objects - Zend Framework Manual

Barcode creation using Zend_Barcode class
Zend_Barcode
Zend Framework手册 中文版
Zend_Barcode Renderers

Zend_Barcode Objects

Barcode objects allow you to generate barcodes independently of the rendering support. After generation, you can retrieve the barcode as an array of drawing instructions that you can provide to a renderer.

Objects have a large number of options. Most of them are common to all objects. These options can be set in four ways:

  • As an array or a Zend_Config object passed to the constructor.

  • As an array passed to the setOptions() method.

  • As a Zend_Config object passed to the setConfig() method.

  • Via individual setters for each configuration type.

Example #1 Different ways to parameterize a barcode object

  1. $options = array('text' => 'ZEND-FRAMEWORK', 'barHeight' => 40);
  2.
  3. // Case 1: constructor
  4. $barcode = new Zend_Barcode_Object_Code39($options);
  5.
  6. // Case 2: setOptions()
  7. $barcode = new Zend_Barcode_Object_Code39();
  8. $barcode->setOptions($options);
  9.
  10. // Case 3: setConfig()
  11. $config  = new Zend_Config($options);
  12. $barcode = new Zend_Barcode_Object_Code39();
  13. $barcode->setConfig($config);
  14.
  15. // Case 4: individual setters
  16. $barcode = new Zend_Barcode_Object_Code39();
  17. $barcode->setText('ZEND-FRAMEWORK')
  18.         ->setBarHeight(40);

Common Options

In the following list, the values have no units; we will use the term "unit." For example, the default value of the "thin bar" is "1 unit". The real units depend on the rendering support (see the renderers documentation for more information). Setters are each named by uppercasing the initial letter of the option and prefixing the name with "set" (e.g. "barHeight" becomes "setBarHeight"). All options have a corresponding getter prefixed with "get" (e.g. "getBarHeight"). Available options are:

Common Options
Option | Data Type | Default Value | Description
barcodeNamespace | String | Zend_Barcode_Object | Namespace of the barcode; for example, if you need to extend the embedding objects
barHeight | Integer | 50 | Height of the bars
barThickWidth | Integer | 3 | Width of the thick bar
barThinWidth | Integer | 1 | Width of the thin
factor | Integer | 1 | Factor by which to multiply bar widths and font sizes
foreColor | Integer | 0 (black) | Color of the bar and the text. Could be provided as an integer or as a HTML value (e.g. "#333333")
backgroundColor | Integer or String | 16777125 (white) | Color of the background. Could be provided as an integer or as a HTML value (e.g. "#333333")
reverseColor | Boolean | FALSE | Allow switching the color of the bar and the background
orientation | Integer | 0 | Orientation of the barcode
font | String or Integer | NULL | Font path to a TTF font or a number between 1 and 5 if using image generation with GD (internal fonts)
fontSize | Integer | 10 | Size of the font (not applicable with numeric fonts)
withBorder | Boolean | FALSE | Draw a border around the barcode and the quiet zones
drawText | Boolean | TRUE | Set if the text is displayed below the barcode
stretchText | Boolean | FALSE | Specify if the text is stretched all along the barcode
withChecksum | Boolean | FALSE | Indicate whether or not the checksum is automatically added to the barcode
withChecksumInText | Boolean | FALSE | Indicate whether or not the checksum is displayed in the textual representation
text | String | NULL | The text to represent as a barcode

Particular case of static setBarcodeFont()

You can set a commont font for all your objects by using the static method Zend_Barcode_Object::setBarcodeFont(). This value can be always be overridden for individual objects by using the setFont() method.

  1. // In your bootstrap:
  2. Zend_Barcode_Object::setBarcodeFont('my_font.ttf');
  3.
  4. // Later in your code:
  5. Zend_Barcode::render(
  6.     'code39',
  7.     'pdf',
  8.     array('text' => 'ZEND-FRAMEWORK')
  9. ); // will use 'my_font.ttf'
  10.
  11. // or:
  12. Zend_Barcode::render(
  13.     'code39',
  14.     'image',
  15.     array(
  16.         'text' => 'ZEND-FRAMEWORK',
  17.         'font' => 3
  18.     )
  19. ); // will use the 3rd GD internal font

Common Additional Getters

Common Getters
Getter | Data Type | Description
getType() | String | Return the name of the barcode class without the namespace (e.g. Zend_Barcode_Object_Code39 returns simply "code39")
getRawText() | String | Return the original text provided to the object
getTextToDisplay() | String | Return the text to display, including, if activated, the checksum value
getQuietZone() | Integer | Return the size of the space needed before and after the barcode without any drawing
getInstructions() | Array | Return drawing instructions as an array.
getHeight($recalculate = false) | Integer | Return the height of the barcode calculated after possible rotation
getWidth($recalculate = false) | Integer | Return the width of the barcode calculated after possible rotation
getOffsetTop($recalculate = false) | Integer | Return the position of the top of the barcode calculated after possible rotation
getOffsetLeft($recalculate = false) | Integer | Return the position of the left of the barcode calculated after possible rotation

Description of shipped barcodes

You will find below detailed information about all barcode types shipped by default with Zend Framework.

Zend_Barcode_Object_Error

< class="inlinemediaobject">

This barcode is a special case. It is internally used to automatically render an exception caught by the Zend_Barcode component.

Zend_Barcode_Object_Code25

< class="inlinemediaobject">

  • Name: Code 25 (or Code 2 of 5 or Code 25 Industrial)

  • Allowed characters: '0123456789'

  • Checksum: optional (modulo 10)

  • Length: variable

There are no particular options for this barcode.

Zend_Barcode_Object_Code25interleaved

< class="inlinemediaobject">

This barcode extends Zend_Barcode_Object_Code25 (Code 2 of 5), and has the same particulars and options, and adds the following:

  • Name: Code 2 of 5 Interleaved

  • Allowed characters: '0123456789'

  • Checksum: optional (modulo 10)

  • Length: variable (always even number of characters)

Available options include:

Zend_Barcode_Object_Code25interleaved Options
Option | Data Type | Default Value | Description
withBearerBars | Boolean | FALSE | Draw a thick bar at the top and the bottom of the barcode.

Note: If the number of characters is not even, Zend_Barcode_Object_Code25interleaved will automatically prepend the missing zero to the barcode text.

Zend_Barcode_Object_Ean2

< class="inlinemediaobject">

This barcode extends Zend_Barcode_Object_Ean5 (EAN 5), and has the same particulars and options, and adds the following:

  • Name: EAN-2

  • Allowed characters: '0123456789'

  • Checksum: only use internally but not displayed

  • Length: 2 characters

There are no particular options for this barcode.

Note: If the number of characters is lower than 2, Zend_Barcode_Object_Ean2 will automatically prepend the missing zero to the barcode text.

Zend_Barcode_Object_Ean5

< class="inlinemediaobject">

This barcode extends Zend_Barcode_Object_Ean13 (EAN 13), and has the same particulars and options, and adds the following:

  • Name: EAN-5

  • Allowed characters: '0123456789'

  • Checksum: only use internally but not displayed

  • Length: 5 characters

There are no particular options for this barcode.

Note: If the number of characters is lower than 5, Zend_Barcode_Object_Ean5 will automatically prepend the missing zero to the barcode text.

Zend_Barcode_Object_Ean8

< class="inlinemediaobject">

This barcode extends Zend_Barcode_Object_Ean13 (EAN 13), and has the same particulars and options, and adds the following:

  • Name: EAN-8

  • Allowed characters: '0123456789'

  • Checksum: mandatory (modulo 10)

  • Length: 8 characters (including checksum)

There are no particular options for this barcode.

Note: If the number of characters is lower than 8, Zend_Barcode_Object_Ean8 will automatically prepend the missing zero to the barcode text.

Zend_Barcode_Object_Ean13

< class="inlinemediaobject">

  • Name: EAN-13

  • Allowed characters: '0123456789'

  • Checksum: mandatory (modulo 10)

  • Length: 13 characters (including checksum)

There are no particular options for this barcode.

Note: If the number of characters is lower than 13, Zend_Barcode_Object_Ean13 will automatically prepend the missing zero to the barcode text.

Zend_Barcode_Object_Code39

< class="inlinemediaobject">

  • Name: Code 39

  • Allowed characters: '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ -.$/+%'

  • Checksum: optional (modulo 43)

  • Length: variable

Note: Zend_Barcode_Object_Code39 will automatically add the start and stop characters ('*') for you.

There are no particular options for this barcode.

Zend_Barcode_Object_Identcode

< class="inlinemediaobject">

This barcode extends Zend_Barcode_Object_Code25interleaved (Code 2 of 5 Interleaved), and inherits some of its capabilities; it also has a few particulars of its own.

  • Name: Identcode (Deutsche Post Identcode)

  • Allowed characters: '0123456789'

  • Checksum: mandatory (modulo 10 different from Code25)

  • Length: 12 characters (including checksum)

There are no particular options for this barcode.

Note: If the number of characters is lower than 12, Zend_Barcode_Object_Identcode will automatically prepend missing zeros to the barcode text.

Zend_Barcode_Object_Itf14

< class="inlinemediaobject">

This barcode extends Zend_Barcode_Object_Code25interleaved (Code 2 of 5 Interleaved), and inherits some of its capabilities; it also has a few particulars of its own.

  • Name: ITF-14

  • Allowed characters: '0123456789'

  • Checksum: mandatory (modulo 10)

  • Length: 14 characters (including checksum)

There are no particular options for this barcode.

Note: If the number of characters is lower than 14, Zend_Barcode_Object_Itf14 will automatically prepend missing zeros to the barcode text.

Zend_Barcode_Object_Leitcode

< class="inlinemediaobject">

This barcode extends Zend_Barcode_Object_Identcode (Deutsche Post Identcode), and inherits some of its capabilities; it also has a few particulars of its own.

  • Name: Leitcode (Deutsche Post Leitcode)

  • Allowed characters: '0123456789'

  • Checksum: mandatory (modulo 10 different from Code25)

  • Length: 14 characters (including checksum)

There are no particular options for this barcode.

Note: If the number of characters is lower than 14, Zend_Barcode_Object_Leitcode will automatically prepend missing zeros to the barcode text.

Zend_Barcode_Object_Planet

< class="inlinemediaobject">

  • Name: Planet (PostaL Alpha Numeric Encoding Technique)

  • Allowed characters: '0123456789'

  • Checksum: mandatory (modulo 10)

  • Length: 12 or 14 characters (including checksum)

There are no particular options for this barcode.

Zend_Barcode_Object_Postnet

< class="inlinemediaobject">

  • Name: Postnet (POSTal Numeric Encoding Technique)

  • Allowed characters: '0123456789'

  • Checksum: mandatory (modulo 10)

  • Length: 6, 7, 10 or 12 characters (including checksum)

There are no particular options for this barcode.

Zend_Barcode_Object_Royalmail

< class="inlinemediaobject">

  • Name: Royal Mail or RM4SCC (Royal Mail 4-State Customer Code)

  • Allowed characters: '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'

  • Checksum: mandatory

  • Length: variable

There are no particular options for this barcode.

Zend_Barcode_Object_Upca

< class="inlinemediaobject">

This barcode extends Zend_Barcode_Object_Ean13 (EAN-13), and inherits some of its capabilities; it also has a few particulars of its own.

  • Name: UPC-A (Universal Product Code)

  • Allowed characters: '0123456789'

  • Checksum: mandatory (modulo 10)

  • Length: 12 characters (including checksum)

There are no particular options for this barcode.

Note: If the number of characters is lower than 12, Zend_Barcode_Object_Upca will automatically prepend missing zeros to the barcode text.

Zend_Barcode_Object_Upce

< class="inlinemediaobject">

This barcode extends Zend_Barcode_Object_Upca (UPC-A), and inherits some of its capabilities; it also has a few particulars of its own. The first character of the text to encode is the system (0 or 1).

  • Name: UPC-E (Universal Product Code)

  • Allowed characters: '0123456789'

  • Checksum: mandatory (modulo 10)

  • Length: 8 characters (including checksum)

There are no particular options for this barcode.

Note: If the number of characters is lower than 8, Zend_Barcode_Object_Upce will automatically prepend missing zeros to the barcode text.

Note: If the first character of the text to encode is not 0 or 1, Zend_Barcode_Object_Upce will automatically replace it by 0.

Barcode creation using Zend_Barcode class
Zend_Barcode
Zend Framework手册 中文版
Zend_Barcode Renderers
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Barcode
  • Introduction
  • Barcode creation using Zend_Barcode class
  • Zend_Barcode Objects
  • Zend_Barcode Renderers


Zend_Barcode Renderers - Zend Framework Manual

Zend_Barcode Objects
Zend_Barcode
Zend Framework手册 中文版
Zend_Cache

Zend_Barcode Renderers

Renderers have some common options. These options can be set in four ways:

  • As an array or a Zend_Config object passed to the constructor.

  • As an array passed to the setOptions() method.

  • As a Zend_Config object passed to the setConfig() method.

  • As discrete values passed to individual setters.

Example #1 Different ways to parameterize a renderer object

  1. $options = array('topOffset' => 10);
  2.
  3. // Case 1
  4. $renderer = new Zend_Barcode_Renderer_Pdf($options);
  5.
  6. // Case 2
  7. $renderer = new Zend_Barcode_Renderer_Pdf();
  8. $renderer->setOptions($options);
  9.
  10. // Case 3
  11. $config   = new Zend_Config($options);
  12. $renderer = new Zend_Barcode_Renderer_Pdf();
  13. $renderer->setConfig($config);
  14.
  15. // Case 4
  16. $renderer = new Zend_Barcode_Renderer_Pdf();
  17. $renderer->setTopOffset(10);

Common Options

In the following list, the values have no unit; we will use the term "unit." For example, the default value of the "thin bar" is "1 unit." The real units depend on the rendering support. The individual setters are obtained by uppercasing the initial letter of the option and prefixing the name with "set" (e.g. "barHeight" => "setBarHeight"). All options have a correspondant getter prefixed with "get" (e.g. "getBarHeight"). Available options are:

Common Options
Option | Data Type | Default Value | Description
rendererNamespace | String | Zend_Barcode_Renderer | Namespace of the renderer; for example, if you need to extend the renderers
horizontalPosition | String | "left" | Can be "left", "center" or "right". Can be useful with PDF or if the setWidth() method is used with an image renderer.
verticalPosition | String | "top" | Can be "top", "middle" or "bottom". Can be useful with PDF or if the setHeight() method is used with an image renderer.
leftOffset | Integer | 0 | Top position of the barcode inside the renderer. If used, this value will override the "horizontalPosition" option.
topOffset | Integer | 0 | Top position of the barcode inside the renderer. If used, this value will override the "verticalPosition" option.
automaticRenderError | Boolean | TRUE | Whether or not to automatically render errors. If an exception occurs, the provided barcode object will be replaced with an Error representation. Note that some errors (or exceptions) can not be rendered.
moduleSize | Float | 1 | Size of a rendering module in the support.
barcode | Zend_Barcode_Object | NULL | The barcode object to render.

An additional getter exists: getType(). It returns the name of the renderer class without the namespace (e.g. Zend_Barcode_Renderer_Image returns "image").

Zend_Barcode_Renderer_Image

The Image renderer will draw the instruction list of the barcode object in an image resource. The component requires the GD extension. The default width of a module is 1 pixel.

Available option are:

Zend_Barcode_Renderer_Image Options
Option | Data Type | Default Value | Description
height | Integer | 0 | Allow you to specify the height of the result image. If "0", the height will be calculated by the barcode object.
width | Integer | 0 | Allow you to specify the width of the result image. If "0", the width will be calculated by the barcode object.
imageType | String | "png" | Specify the image format. Can be "png", "jpeg", "jpg" or "gif".

Zend_Barcode_Renderer_Pdf

The PDF renderer will draw the instruction list of the barcode object in a PDF document. The default width of a module is 0.5 point.

There are no particular options for this renderer.

Zend_Barcode Objects
Zend_Barcode
Zend Framework手册 中文版
Zend_Cache
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Barcode
  • Introduction
  • Barcode creation using Zend_Barcode class
  • Zend_Barcode Objects
  • Zend_Barcode Renderers


Zend_Cache - Zend Framework Manual

Zend_Barcode Renderers
Zend Framework Reference
Zend Framework手册 中文版
简介

Zend_Cache

Table of Contents
  • 简介
  • 缓存原理
  • Zend_Cache前端
  • Zend_Cache后端
  • The Cache Manager
Zend_Barcode Renderers
Zend Framework Reference
Zend Framework手册 中文版
简介
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


简介 - Zend Framework Manual

Zend_Cache
Zend_Cache
Zend Framework手册 中文版
缓存原理

简介

Zend_Cache 提供了一个缓存任何数据的一般方法.

在Zend Framework中缓存由前端操作,同时通过后端适配器(File, Sqlite, Memcache...)和 一个灵活的IDs和Tags系统(标识符和标记系统)存储缓存纪录.使用此方法,易于删除特定类型的纪录(例如:"删除所有标记为tag的纪录")

模块(Zend_Cache_Core) 的核心是通用,灵活和可配置.对于特定的需要,为了便捷,这里有一些继承自Zend_Cache_Core的前端: Output, File, Function 和 Class.

Example #1 调用 Zend_Cache::factory()取得一个前端

Zend_Cache::factory() 实例化正确的对象并把他们捆绑到一起. 在这第一个例子中我们将把 Core 前端和 File 后端一起使用.

$frontendOptions = array(
   'lifeTime' => 7200, // 两小时的缓存生命期
   'automatic_serialization' => true
);

$backendOptions = array(
    'cache_dir' => './tmp/' // 放缓存文件的目录
);

// 取得一个Zend_Cache_Core 对象
$cache = Zend_Cache::factory('Core',
                             'File',
                             $frontendOptions,
                             $backendOptions);

Note: 由多个字组成的前端和后端
 一些前端和后端使用多个字命名,例如'ZendPlatform'.当指定给工厂时,使用字分隔符,比如空格(' '),连字符('-'),或则点('.').

Example #2 Caching a database query result

现在有了一个前端,可用缓存任何类型的数据了(开了序列化'serialization').例如,能够缓存从昂贵的数据库查询中缓存一个结果.结果被缓存后,不再需要连接到数据库;数据直接在缓存中取回和反序列化.

// $cache 在先前的例子中已经初始化了

// 查看一个缓存是否存在:
if(!$result = $cache->load('myresult')) {

    // 缓存不命中;连接到数据库

    $db = Zend_Db::factory( [...] );

    $result = $db->fetchAll('SELECT * FROM huge_table');

    $cache->save($result, 'myresult');

} else {

    // cache hit! shout so that we know
    echo "This one is from cache!\n\n";

}

print_r($result);

Example #3 用Zend_Cache 输出前端缓存输出

通过加入条件逻辑,我们'mark up'(标记)那些希望缓存输出的段(sections),在start() 和 end()方法间封装这些section(这类似第一个例子,并且是缓存的核心策略).

在内部,像往常一样输出你的数据,当执行到end()方法时,所有之前的输出都被缓存.在下一次运行时,整个段(end()方法调用前的代码)将被跳过执行,直接从Cache中取回数据(只要缓存纪录是有效的).

$frontendOptions = array(
   'lifeTime' => 30,                  // cache lifetime of 30 seconds
   'automatic_serialization' => false  // this is the default anyway s
);
// 翻译时实验系统为Windows,请使用Windows的读者修改cacheDir的路径为实际的路径
$backendOptions = array('cache_dir' => './tmp/');

$cache = Zend_Cache::factory('Output',
                             'File',
                             $frontendOptions,
                             $backendOptions);

// 传递一个唯一标识符给start()方法
if(!$cache->start('mypage')) {
    // output as usual:

    echo 'Hello world! ';
    echo 'This is cached ('.time().') ';

    $cache->end(); // the output is saved and sent to the browser
}

echo 'This is never cached ('.time().').';

注意我们两次输出了time()的结果;为演示目的第二次的time()调用是动态的.再运行然后刷新多次;你会注意到当随着时间的流逝第一个数字并没有随时间改变.这是因为第一个数组在缓存段中输出,因此输出是被缓存了. 30秒后(我们设置了lifetime为30秒)由于缓存纪录超时而变得无效了,第一个数字再次更新,同时于第二个时间匹配(相同).你应该在你的浏览器或者控制台中试一下.

Note: 在使用Zend_Cache是特别要注意的Cache标识(传递给save()和start()的参数).它必须对于你所缓存的每个资源唯一,否则不相关的缓存纪录就会相互覆盖, 更糟的是,导致错误的显示结果.

Zend_Cache
Zend_Cache
Zend Framework手册 中文版
缓存原理
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Cache
  • 简介
  • 缓存原理
  • Zend_Cache前端
  • Zend_Cache后端
  • The Cache Manager


缓存原理 - Zend Framework Manual

简介
Zend_Cache
Zend Framework手册 中文版
Zend_Cache前端

缓存原理

在Zend_Cache中有三个关键概念.一是用于标识缓存纪录的唯一标识符(一个字符串).二是'lifeTime'指令,正如例子中所见, 它定义了缓存纪录的生命期(超过该值,缓存纪录被销毁).第三个关键概念是条件执行,你的部分代码可用被跳过,以加速性能. 前端函数(例如. Zend_Cache_Core::get())在缓存不命中时返回false,这使用户能处理if(){ ... } 语句中的条件,包含代码中他们所要缓存(或者跳过)的部分,最后是否必须保存这些你曾经生成的块(例如: Zend_Cache_Core::save()).

Note: 在有些前端Function中不需要条件执行,例如,当整个逻辑在前端内部实现的时候.

Note: '缓存命中'是一个术语,它表示当一个缓存纪录发现可用,是有效的并且是'fresh'的(换言之,就是还没有过期).'Cache miss' 表示当在缓存中找不到需要的数据时,发生缓存不命中. 当一个Cache miss发生是,你必须生成你的数据,并使它被缓存.而对于缓存命中,后端自动透明地从Cache中取回缓存纪录.

Zend_Cache 工厂方法

下面的示例给出了一个构造Zend_Cache前端实例的好方法:

// We choose a backend (for example 'File' or 'Sqlite'...)
$backendName = '[...]';

// 选择一个前端(例如'Core', 'Output', 'Page'...)
$frontendName = '[...]';

// 为选择的前端设置一个选项数组
$frontendOptions = array([...]);

// 为选择的后端设置一个选项数组
$backendOptions = array([...]);

// 创建实例(当然,最后两个参数是可选的)
$cache = Zend_Cache::factory($frontendName, $backendName, $frontendOptions, $backendOptions);

在下面的例子中我们假设变量$cache保存有一个有效的,已实例化的前端,并且你知道该如何给你选择的后端传递参数.

Note: 必须使用Zend_Cache::factory()来得到前端实例.你自己 直接实例化的 前端或者后端 不能按照期望工作.

标记纪录

标记是给缓存纪录分类的一种方法.当你使用save()方法保存一个缓存时,你可以给该缓存纪录设置一个或多个标记,多个标记以数组形式组织在一起 此后你不再需要该缓存纪录使,你可以清除所有指定标记的缓存纪录.

$cache->save($huge_data, 'myUniqueID', array('tagA', 'tagB', 'tagC'));

Note: note than the save() method accepts an optional fourth argument : $specificLifetime (if != false, it sets a specific lifetime for this particular cache record)

缓存清理

删除特定id的Cache纪录,使用remove()方法:

$cache->remove('idToRemove');

在单个操作中删除多个Cache纪录,可以使用clean()方法.例如,删除所有的缓存纪录:

// 清除所有缓存纪录
$cache->clean(Zend_Cache::CLEANING_MODE_ALL);

// 仅清除过期的
$cache->clean(Zend_Cache::CLEANING_MODE_OLD);

如果你想删除标记为'tagA'和'tagC'的缓存项:

$cache->clean(Zend_Cache::CLEANING_MODE_MATCHING_TAG, array('tagA', 'tagC'));

可用的清除模式有:CLEANING_MODE_ALL, CLEANING_MODE_OLD, CLEANING_MODE_MATCHING_TAG 和 CLEANING_MODE_NOT_MATCHING_TAG. 后面的,正如它名称所暗示的,在清除操作中组合了一个标记数组,对其中的每个元素作处理.

简介
Zend_Cache
Zend Framework手册 中文版
Zend_Cache前端
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Cache
  • 简介
  • 缓存原理
  • Zend_Cache前端
  • Zend_Cache后端
  • The Cache Manager


Zend_Cache后端 - Zend Framework Manual

Zend_Cache前端
Zend_Cache
Zend Framework手册 中文版
The Cache Manager

Zend_Cache后端

Zend_Cache_Backend_File

此后端把缓存纪录存储到文件中去(在一个选定的目录中).

可用的选项有 :

文件后端选项
选项 | 数据类型 | 默认值 | 描述
cache_dir | string | '/tmp/' | 存放缓存文件的目录
file_locking | boolean | true | 启用/禁用文件锁定 : 在比较坏的情况下,能够避免缓存中断,但在多线程Web服务器或者NFS文件系统中没有任何帮助.
read_control | boolean | true | 启用/禁用读控制: 如果启用,控制键被嵌入到缓存文件中,并且这个键将与读取后计算出的值进行比较.
read_control_type | string | 'crc32' | 读控制类型 (仅在读控制启用时). 可用的值有: 'md5' (最好但最慢), 'crc32' (安全性稍差,但更快,更好的选择), 'adler32' (新选择，比 crc32 快), 'strlen' for a length only test (最快).
hashed_directory_level | int | 0 | Hash目录结构层次: 0 表示"不使用hash的目录结构", 1 表示"一级目录结构" , 2表示"二级目录"... 次选项在你有成千上万的缓存文件是能够加速缓存.只有相关的基准测试才能帮助你选择合适的值.也许1或2是一个好的开始.
hashed_directory_umask | int | 0700 | 目录结构的Unix 掩码
file_name_prefix | string | 'zend_cache' | 缓存文件前缀;小心使用此选项,因为当清除缓存时,在系统缓存目录(像 /tmp)中一个太generic的值将导致灾难.
cache_file_umask | int | 0700 | 缓存文件掩码
metatadatas_array_max_size | int | 100 | metadatas 数组的内部最大尺寸（除非你知道你在做什么，不要更改这个值）

Zend_Cache_Backend_Sqlite

此后端把缓存纪录存储到SQLite数据库中.

可用的选项有:

Sqlite 后端选项
选项 | 数据类型 | 默认值 | 描述
cache_db_complete_path (mandatory) | string | null | SQLite数据库的完整和路径(包括文件名)
automatic_vacuum_factor | int | 10 | 禁用 / 调整自动清理过程. 自动清理过程将对数据库文件进行碎片整理(and make it smaller) 当clean() 或则 delete() 被调用时 : 0 表示不自动清理; 1 表示自动清理(当调用 delete() 或者 clean() 方法时) ; x (整数) > 1 => 当调用 delete() 或者 clean() 方法时随机清理1到x次.

Zend_Cache_Backend_Memcached

本后端把缓存纪录存储到memcached服务器. » memcached 是一个高性能的,分布式内存对象缓存系统.要使用此后端,你需要一个memecached守护进程(daemon)和 » memcache PECL 扩展.

注意 : 使用此后端当设置"doNotTestCacheValidity=true"参数时,不支持"tags"

可用的选项有:

Memcached 后端选项
选项 | 数据类型 | 默认值 | 描述
servers | array | array(array('host' => 'localhost','port' => 11211, 'persistent' => true)) | 一个memcached服务器数组;其中每个memcached服务器描述为一个关联数组: 'host' => (string) : memcached服务器的名称, 'port' => (int) : memcached服务器端口, 'persistent' => (bool) : 是否使用到memcached服务器的持久连接
compression | boolean | false | 如果你想使用数据压缩,设置为true

Zend_Cache_Backend_Apc

此后端通过 » APC (Alternative PHP Cache) 扩展把缓存纪录存储于共享内存中 (当然为使用此后端,APC是需要的).

注意 : 使用此后端当设置"doNotTestCacheValidity=true"参数时,不支持"tags"

此后端没有选项.

Zend_Cache_Backend_Xcache

整个后端通过 » XCache 扩展（它当然需要使用这个后端） 在共享内存里存储了缓存记录。

小心：用这个后端，目前不支持 ”tags“，因为 "doNotTestCacheValidity=true" 参数。

可用的选项如下：

Xcache backend 选项
选项 | 数据类型 | 缺省值 | 描述
user | string | null | xcache.admin.user, necessary for the clean() method
password | string | null | xcache.admin.pass (in clear form, not MD5), necessary for the clean() method

Zend_Cache_Backend_ZendPlatform

本后端使用 » Zend Platform产品的内容缓存API. 要使用此后端必须安装Zend Platform.

本后端支持标记(tags),但不支持 CLEANING_MODE_NOT_MATCHING_TAG清除模式.

当使用Zend_Cache::factory()方法时,在字 'Zend' 和 'Platform'之间使用字分隔符-- '-', '.', ' ', or '_'指定此后端:

$cache = Zend_Cache::factory('Core', 'Zend Platform');

此后端没有选项.

Zend_Cache前端
Zend_Cache
Zend Framework手册 中文版
The Cache Manager
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Cache
  • 简介
  • 缓存原理
  • Zend_Cache前端
  • Zend_Cache后端
  • The Cache Manager


Zend_Cache前端 - Zend Framework Manual

缓存原理
Zend_Cache
Zend Framework手册 中文版
Zend_Cache后端

Zend_Cache前端

Zend_Cache_Core

简介

Zend_Cache_Core是一个特别的前端,因为他是模块的核心. 它是一个一般化(generic)的缓存前端,并且由其他类扩展.

Note: 所有的前端继承自Zend_Cache_Core因此它的方法和选项(描述如下)应该在其他的前端中可用,所以这里没有进行文档化.

可用选项

这些选项被传递给如前面例子中演示的工厂方法.

核心前端选项
选项 | 数据类型 | 默认值 | 描述
caching | boolean | true | 打开 / 关闭缓存 (对被缓存脚本的调试非常有用)
cache_id_prefix | string | null | 所有缓存 id 的前缀，如果设置为 null ，没有缓存 id 前缀使用。 缓存 id 前缀在缓存里创建一个命名空间，允许多个程序和网上共享缓存。 每个程序或网站可以使用不同的缓存 id 前缀，所以特定的缓存 id 可以使用多次。
lifetime | int | 3600 | 缓存生命期(秒), 如果设置为 null, 缓存永远有效.
logging | boolean | false | 如果设置为true,日志纪录(通过使用Zend_Log)被激活(但是系统将变慢)
write_control | boolean | true | 打开 / 关闭 写控制 （the cache is read just after writing to detect corrupt entries），打开写控制轻微地放慢缓存写的速度但不影响读（it can detect some corrupt cache files but it's not a perfect control）
automatic_serialization | boolean | false | 打开 / 关闭自动序列化, 可以直接用于保存非字符串数据(但是很慢)
automatic_cleaning_factor | int | 10 | 关闭 / 调整自动清理过程 (垃圾收集器): 0 表示不自动清理缓存,1 表示自动清理缓存,并且如果x > 1 表示x写操作后自动随机清理1次.
ignore_user_abort | boolean | false | 如果设置为 true，核心将在 save() 方法里设置 ignore_user_abort PHP flag，以免在某些情况下缓存崩溃。

例子

An example is given in the manual at the very beginning.

如果你只向缓存中存储字符串(由于"automatic_serialization"选项,可能会存储一些布尔值),你可以使用更加简介的构造:

// 假定你已经有 $cache

$id = 'myBigLoop'; // cache id of "what we want to cache"

if (!($data = $cache->load($id))) {
    // cache miss

    $data = '';
    for ($i = 0; $i < 10000; $i++) {
        $data = $data . $i;
    }

    $cache->save($data);

}

// [...] do something with $data (echo it, pass it on etc.)

如果你缓存多个块或则数据实例,意思是一样的:

// 确保使用独一无二的 identifiers:
$id1 = 'foo';
$id2 = 'bar';

// block 1
if (!($data = $cache->load($id1))) {
    // cache missed

    $data = '';
    for ($i=0;$i<10000;$i++) {
        $data = $data . $i;
    }

    $cache->save($data);

}
echo($data);

// this isn't affected by caching
echo('NEVER CACHED! ');

// block 2
if (!($data = $cache->load($id2))) {
    // cache missed

    $data = '';
    for ($i=0;$i<10000;$i++) {
        $data = $data . '!';
    }

    $cache->save($data);

}
echo($data);

如果你想缓存特殊值（带 "automatic_serialization" 选项的布尔值）或不能用上述紧缩结构的空字符串，你需要正式地测试缓存记录。

// the compact construction
// (not good if you cache empty strings and/or booleans)
if (!($data = $cache->load($id))) {

    // cache missed

    // [...] we make $data

    $cache->save($data);

}

// we do something with $data

// [...]

// the complete construction (works in any case)
if (!($cache->test($id))) {

    // cache missed

    // [...] we make $data

    $cache->save($data);

} else {

    // cache hit

    $data = $cache->load($id);

}

// we do something with $data

Zend_Cache_Frontend_Output

简介

Zend_Cache_Frontend_Output 是一个输出捕捉前端.它在PHP中使用输出缓冲捕获start() 和 end() 方法间的一切输出.

可用的选项

该前端除了Zend_Cache_Core那些选项外没有任何特定的选项.

例子

An example is given in the manual at the very beginning. Here it is with minor changes:

// if it is a cache miss, output buffering is triggered
if (!($cache->start('mypage'))) {

    // output everything as usual
    echo 'Hello world! ';
    echo 'This is cached ('.time().') ';

    $cache->end(); // output buffering ends

}

echo 'This is never cached ('.time().').';

Using this form it is fairly easy to set up output caching in your already working project with little or no code refactoring.

Zend_Cache_Frontend_Function

Introduction

Zend_Cache_Frontend_Function caches the results of function calls. It has a single main method named call() which takes a function name and parameters for the call in an array.

A可用的选项

函数前端选项
选项 | 数据类型 | 默认值 | 描述
cache_by_default | boolean | true | 如果为true,默认情况下,函数调用将被缓存.
cached_functions | array |  | 函数名称总是被缓存
non_cached_functions | array |  | 决不缓存函数名称

例子

在PHP中使用 call() 函数于使用 call_user_func_array()相同:

$cache->call('veryExpensiveFunc', $params);

// $params is an array
// For example to call veryExpensiveFunc(1, 'foo', 'bar') with
// caching, you can use
// $cache->call('veryExpensiveFunc', array(1, 'foo', 'bar'))

Zend_Cache_Frontend_Function is smart enough to cache both the return value of the function and its internal output.

Note:
                You can pass any built in or user defined function with the exception of
                array(), echo(), empty(), eval(),
                exit(), isset(), list(), print()
                and unset().

Zend_Cache_Frontend_Class

Introduction

Zend_Cache_Frontend_Class is different from Zend_Cache_Frontend_Function because it allows caching of object and static method calls.

Available options

Class frontend options
Option | Data Type | Default Value | Description
cached_entity (required) | mixed |  | if set to a class name, we will cache an abstract class and will use only static calls; if set to an object, we will cache this object methods
cache_by_default | boolean | true | if true, calls will be cached by default
cached_methods | array |  | method names which will always be cached
non_cached_methods | array |  | method names which must never be cached

Examples

For example, to cache static calls :

class test {

    // Static method
    public static function foobar($param1, $param2) {
        echo "foobar_output($param1, $param2)";
        return "foobar_return($param1, $param2)";
    }

}

// [...]
$frontendOptions = array(
    'cached_entity' => 'Test' // The name of the class
);
// [...]

// The cached call
$result = $cache->foobar('1', '2');

To cache classic method calls :

class Test {

    private $_string = 'hello !';

    public function foobar2($param1, $param2) {
        echo($this->_string);
        echo "foobar2_output($param1, $param2)";
        return "foobar2_return($param1, $param2)";
    }

}

// [...]
$frontendOptions = array(
    'cached_entity' => new Test() // An instance of the class
);
// [...]

// The cached call
$result = $cache->foobar2('1', '2');

Zend_Cache_Frontend_File

Introduction

Zend_Cache_Frontend_File is a frontend driven by the modification time of a "master file". It's really interesting for examples in configuration or templates issues.

For instance, you have an XML configuration file which is parsed by a function which returns a "config object" (like with Zend_Config). With Zend_Cache_Frontend_File, you can store the "config object" into cache (to avoid the parsing of the XML config file at each time) but with a sort of strong dependency on the "master file". So, if the XML config file is modified, the cache is immediately invalidated.

Available options

File frontend options
Option | Data Type | Default Value | Description
master_file (mandatory) | string |  | the complete path and name of the master file

Examples

Use of this frontend is the same than of Zend_Cache_Core. There is no need of a specific example - the only thing to do is to define the master_file when using the factory.

Zend_Cache_Frontend_Page

Introduction

Zend_Cache_Frontend_Page is like Zend_Cache_Frontend_Output but designed for a complete page. It's impossible to use Zend_Cache_Frontend_Page for caching only a single block.

On the other hand, the "cache id" is calculated automatically with $_SERVER['REQUEST_URI'] and (depending on options) $_GET, $_POST, $_SESSION, $_COOKIE, $_FILES. More over, you have only one method to call (start()) because the end() call is fully automatic when the page is ended.

For the moment, it's not implemented but we plan to add a HTTP conditional system to save bandwidth (the system will send a HTTP 304 Not Modified if the cache is hit and if the browser has already the good version).

Available options (for this frontend in Zend_Cache factory)

Page frontend options
Option | Data Type | Default Value | Description
http_conditional | boolean | false | use the http_conditional system (not implemented for the moment)
debug_header | boolean | false | if true, a debug text is added before each cached pages
default_options array array(...see below...) an associative array of default options :

  • (boolean, true by default) cache : cache is on if true

  • (boolean, false by default) cache_with_get_variables : if true, cache is still on even if there are some variables in $_GET array

  • (boolean, false by default) cache_with_post_variables : if true, cache is still on even if there are some variables in $_POST array

  • (boolean, false by default) cache_with_session_variables : if true, cache is still on even if there are some variables in $_SESSION array

  • (boolean, false by default) cache_with_files_variables : if true, cache is still on even if there are some variables in $_FILES array

  • (boolean, false by default) cache_with_cookie_variables : if true, cache is still on even if there are some variables in $_COOKIE array

  • (boolean, true by default) make_id_with_get_variables : if true, the cache id will be dependent of the content of the $_GET array

  • (boolean, true by default) make_id_with_post_variables : if true, the cache id will be dependent of the content of the $_POST array

  • (boolean, true by default) make_id_with_session_variables : if true, the cache id will be dependent of the content of the $_SESSION array

  • (boolean, true by default) make_id_with_files_variables : if true, the cache id will be dependent of the content of the $_FILES array

  • (boolean, true by default) make_id_with_cookie_variables : if true, the cache id will be dependent of the content of the $_COOKIE array

regexps | array | array() | an associative array to set options only for some REQUEST_URI, keys are (PCRE) regexps, values are associative arrays with specific options to set if the regexp matchs on $_SERVER['REQUEST_URI'] (see default_options for the list of available options) ; if several regexps match the $_SERVER['REQUEST_URI'], only the last one will be used
memorize_headers | array | array() | 对应于一些 HTTP 头名称的字符串数组。列表中的头将保存在缓存里，需要的时候就调出来。

Examples

Use of Zend_Cache_Frontend_Page is really trivial :

// [...] // require, configuration and factory

$cache->start();
// if the cache is hit, the result is sent to the browser and the script stop here

// rest of the page ...

a more complex example which shows a way to get a centralized cache management in a bootstrap file (for using with Zend_Controller for example)

/*
 * you should avoid putting too many lines before the cache section.
 * For example, for optimal performances, "require_once" or
 * "Zend_Loader::loadClass" should be after the cache section.
 */

$frontendOptions = array(
   'lifetime' => 7200,
   'debug_header' => true, // for debugging
   'regexps' => array(
       // cache the whole IndexController
       '^/$' => array('cache' => true),

       // cache the whole IndexController
       '^/index/' => array('cache' => true),

       // we don't cache the ArticleController...
       '^/article/' => array('cache' => false),

       // ... but we cache the "view" action of this ArticleController
       '^/article/view/' => array(
           'cache' => true,

           // and we cache even there are some variables in $_POST
           'cache_with_post_variables' => true,

           // but the cache will be dependent on the $_POST array
           'make_id_with_post_variables' => true
       )
   )
);

$backendOptions = array(
    'cache_dir' => '/tmp/'
);

// getting a Zend_Cache_Frontend_Page object
$cache = Zend_Cache::factory('Page',
                             'File',
                             $frontendOptions,
                             $backendOptions);

$cache->start();
// if the cache is hit, the result is sent to the browser and the
// script stop here

// [...] the end of the bootstrap file
// these lines won't be executed if the cache is hit

特殊的取消方法

因为设计问题，在有些情况下（例如使用非 HTTP/200 返回代码时），你可能需要取消当前缓存处理，所以 我们引入这个特别的前端，cancel()方法。

// [...] // require, configuration and factory

$cache->start();

// [...]

if ($someTest) {
    $cache->cancel();
    // [...]
}

// [...]
缓存原理
Zend_Cache
Zend Framework手册 中文版
Zend_Cache后端
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Cache
  • 简介
  • 缓存原理
  • Zend_Cache前端
  • Zend_Cache后端
  • The Cache Manager


The Cache Manager - Zend Framework Manual

Zend_Cache后端
Zend_Cache
Zend Framework手册 中文版
Zend_Captcha

The Cache Manager

It's the nature of applications to require a multitude of caches of any type often dependent on the controller, library or domain model being accessed. To allow for a simple means of defining Zend_Cache options in advance (such as from a bootstrap) so that accessing a cache object requires minimum setup within the application source code, the Zend_Cache_Manager class was written. This class is accompanied by Zend_Application_Resource_Cachemanager ensuring bootstrap configuration is available and Zend_Controller_Action_Helper_Cache to allow simple cache access and instantiation from controllers and other helpers.

The basic operation of this component is as follows. The Cache Manager allows users to setup "option templates", basically options for a set of named caches. These can be set using the method Zend_Cache_Manager::setCacheTemplate(). These templates do not give rise to a cache until the user attempts to retrieve a named cache (associated with an existing option template) using the method Zend_Cache_Manager::getCache().

  1. $manager = new Zend_Cache_Manager;
  2.
  3. $dbCache = array(
  4.     'frontend' => array(
  5.         'name' => 'Core',
  6.         'options' => array(
  7.             'lifetime' => 7200,
  8.             'automatic_serialization' => true
  9.         )
  10.     ),
  11.     'backend' => array(
  12.         'name' => 'Core',
  13.         'options' => array(
  14.             'cache_dir' => '/path/to/cache'
  15.         )
  16.     )
  17. );
  18.
  19. $manager->setCacheTemplate('database', $dbCache);
  20.
  21. /**
  22. * Anywhere else where the Cache Manager is available...
  23. */
  24. $databaseCache = $manager->getCache('database');

The Cache Manager also allows simple setting of pre-instantiated caches using the method Zend_Cache_Manager::setCache().

  1. $frontendOptions = array(
  2.    'lifetime' => 7200,
  3.    'automatic_serialization' => true
  4. );
  5.
  6. $backendOptions = array(
  7.     'cache_dir' => '/path/to/cache'
  8. );
  9.
  10. $dbCache = Zend_Cache::factory('Core',
  11.                              'File',
  12.                              $frontendOptions,
  13.                              $backendOptions);
  14.
  15. $manager = new Zend_Cache_Manager;
  16. $manager->setCache('database', $dbCache);
  17.
  18. /**
  19. * Anywhere else where the Cache Manager is available...
  20. */
  21. $databaseCache = $manager->getCache('database');

If for any reason, you are unsure where the Cache Manager contains a pre-instantiated cache or a relevant option cache template to create one on request, you can check for the existance of a name cache configuration or instance using the method Zend_Cache_Manager::hasCache().

  1. $manager = new Zend_Cache_Manager;
  2.
  3. $dbCache = array(
  4.     'frontend' => array(
  5.         'name' => 'Core',
  6.         'options' => array(
  7.             'lifetime' => 7200,
  8.             'automatic_serialization' => true
  9.         )
  10.     ),
  11.     'backend' => array(
  12.         'name' => 'Core',
  13.         'options' => array(
  14.             'cache_dir' => '/path/to/cache'
  15.         )
  16.     )
  17. );
  18.
  19. $manager->setCacheTemplate('database', $dbCache);
  20.
  21. /**
  22. * Anywhere else where the Cache Manager is available...
  23. */
  24. if ($manager->hasCache('database')) {
  25.     $databaseCache = $manager->getCache('database');
  26. } else {
  27.     // create a cache from scratch if none available from Manager
  28. }

In some scenarios, you may have defined a number of general use caches using Zend_Cache_Manager but need to fine-tune their options before use depending on the circumstances. You can edit previously set cache templates on the fly before they are instantiated using the method Zend_Cache_Manager::setTemplateOptions().

  1. $manager = new Zend_Cache_Manager;
  2.
  3. $dbCache = array(
  4.     'frontend' => array(
  5.         'name' => 'Core',
  6.         'options' => array(
  7.             'lifetime' => 7200,
  8.             'automatic_serialization' => true
  9.         )
  10.     ),
  11.     'backend' => array(
  12.         'name' => 'Core',
  13.         'options' => array(
  14.             'cache_dir' => '/path/to/cache'
  15.         )
  16.     )
  17. );
  18.
  19. $manager->setCacheTemplate('database', $dbCache);
  20.
  21. /**
  22. * Anywhere else where the Cache Manager is available...
  23. * Here we decided to store some upcoming database queries to Memcached instead
  24. * of the preconfigured File backend.
  25. */
  26. $fineTuning = array(
  27.     'backend' => array(
  28.         'name' => 'Memcached',
  29.         'options' => array(
  30.             'servers' => array(
  31.                 array(
  32.                     'host' => 'localhost',
  33.                     'port' => 11211,
  34.                     'persistent' => true,
  35.                     'weight' => 1,
  36.                     'timeout' => 5,
  37.                     'retry_interval' => 15,
  38.                     'status' => true,
  39.                     'failure_callback' => ''
  40.                 )
  41.             )
  42.         )
  43.     )
  44. );
  45. $manager->setTemplateOptions('database', $fineTuning);
  46. $databaseCache = $manager->getCache('database');

To assist in making the Cache Manager more useful, it is accompanied by Zend_Application_Resource_Cachemanager and also the Zend_Controller_Action_Helper_Cache Action Helper. Both of these are described in their relevant areas of the Reference Guide.

Out of the box, Zend_Cache_Manager already includes four pre-defined cache templates called "skeleton", "default", "page" and "tagcache". The default cache is a simple File based cache using the Core frontend which assumes a cache_dir called "cache" exists at the same level as the conventional "public" directory of a Zend Framework application. The skeleton cache is actually a NULL cache, i.e. it contains no options. The remaining two caches are used to implement a default Static Page Cache where static HTML, XML or even JSON may be written to static files in /public. Control over a Static Page Cache is offered via Zend_Controller_Action_Helper_Cache, though you may alter the settings of this "page" the "tagcache" it uses to track tags using Zend_Cache_Manager::setTemplateOptions() or even Zend_Cache_Manager::setCacheTemplate() if overloading all of their options.

Zend_Cache后端
Zend_Cache
Zend Framework手册 中文版
Zend_Captcha
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Cache
  • 简介
  • 缓存原理
  • Zend_Cache前端
  • Zend_Cache后端
  • The Cache Manager


Zend_Captcha - Zend Framework Manual

The Cache Manager
Zend Framework Reference
Zend Framework手册 中文版
简介

Zend_Captcha

Table of Contents
  • 简介
  • Captcha 操作
  • Captcha 适配器
The Cache Manager
Zend Framework Reference
Zend Framework手册 中文版
简介
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


简介 - Zend Framework Manual

Zend_Captcha
Zend_Captcha
Zend Framework手册 中文版
Captcha 操作

简介

» CAPTCHA 的意思是 "Completely Automated Turing test to tell Computers and Humans Apart;" 它用来询问响应（challenge-response）来确保每个提交的信息是来自人而不是机器的自动处理。 一般地，captcha 用于用户不需要认证的表单提交，但你想防止垃圾信息的提交。

Captcha 可带有许多表单，包括问逻辑问题、现实变形字体和图像并询问它们的关系。 Zend_Captcha 的目标是提供各种各样的后台支持，既可独立使用也可以和 Zend_Form 一起使用。

Zend_Captcha
Zend_Captcha
Zend Framework手册 中文版
Captcha 操作
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Captcha
  • 简介
  • Captcha 操作
  • Captcha 适配器


Captcha 操作 - Zend Framework Manual

简介
Zend_Captcha
Zend Framework手册 中文版
Captcha 适配器

Captcha 操作

所有具体的 CAPTCHA 对象实现 Zend_Captcha_Adapter，如下所示：

interface Zend_Captcha_Adapter extends Zend_Validate_Interface
{
    public function generate();

    public function render(Zend_View $view, $element = null);

    public function setName($name);

    public function getName();

    public function getDecorator();

    // Additionally, to satisfy Zend_Validate_Interface:
    public function isValid($value);

    public function getMessages();

    public function getErrors();
}

增变器和访问器用于指定和获取 captcha 的标识符。 getDecorator() 可用通过名称或返回一个装饰器对象来指定一个 Zend_Form 装饰器。 然而用法的关键之处是 generate() 和 render()。 generate() 用于生成 captcha 令牌。这个过程一般存储令牌到会话，所以你 可以根据后来的请求来比较。 render() 用来解析表示 captcha 的信息 － 可以是图像、figlet 或逻辑问题等。

一般的用例如下：

// Originating request:
$captcha = new Zend_Captcha_Figlet(array(
    'name' => 'foo',
    'wordLen' => 6,
    'timeout' => 300,
));
$id = $captcha->generate();
echo $captcha->render();

// On subsequent request:
// Assume captcha setup as before, and $value is the submitted value:
if ($captcha->isValid($_POST['foo'], $_POST)) {
    // Validated!
}
简介
Zend_Captcha
Zend Framework手册 中文版
Captcha 适配器
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Captcha
  • 简介
  • Captcha 操作
  • Captcha 适配器


Captcha 适配器 - Zend Framework Manual

Captcha 操作
Zend_Captcha
Zend Framework手册 中文版
Zend_CodeGenerator

Captcha 适配器

Zend Framework 缺省地带有下列适配器。

Zend_Captcha_Word

Zend_Captcha_Word 是个摘要适配器，它是 Dumb、Figlet 和 Image 适配器的基础。 ，它提供了增变器用来指定字符长度、会话 TTL 、会话命名空间对象，如果你不想 使用 Zend_Session_Namespace，它提供了会话命名空间来用于持久。 另外，它封装了所有校验逻辑。

缺省地，字符长度为 8，会话超时为 5 分钟，Zend_Session_Namespace 用于持久（使用命名空间"Zend_Form_Captcha_<captcha ID>"）。

除了 Zend_Captcha_Adapter 接口要求的标准方法外， Zend_Captcha_Word 还有下列方法：

  • setWordLen($length) 和 getWordLen() 指定生成的“字符”的长度和获取当前值。

  • setTimeout($ttl) 和 getTimeout() 指定会话令牌的 time-to-live 和获取当前值。$ttl 以秒计。

  • setSessionClass($class) 和 getSessionClass() 指定替代的 Zend_Session_Namespace 实现来持久 captcha 令牌和获取当前值。

  • getId() 获取当前令牌标识符。

  • getWord() 获取用于 captcha 的生成字符，如果以前没有生成，它将生成一个。

  • setSession(Zend_Session_Namespace $session) 指定一个会话对象用来持久 captcha 令牌； getSession() 获取当前会话对象。

所有字符 captchas 传递一个选项数组给构造器，或者把它们传递给 setOptions() （或传递一个 Zend_Config 对象给 setConfig()）。 缺省地，可能使用所有的键 wordLen、 timeout 和 sessionClass ；每个具体的实现可能定义另外的键或选项。

Note: 记住，Word 是个摘要类并且可能不能直接初始化。

Zend_Captcha_Dumb

Dumb 适配器通常是自解释的。它提供了随机字符串需要用反序输入来校验。 这样，它不是一个好的 CAPTCHA 方案，只用于测试或者最后的方案。 它继承 Zend_Captcha_Word。

Zend_Captcha_Figlet

Figlet 适配器利用 Zend_Text_Figlet 来展示一个 Figlet 给用户。Figlet captchas 只限于字符。

传递给构造器的选项也可以传递给适配器使用的 Zend_Text_Figlet 对象。 请参考关于配置选项的细节的文档。

Zend_Captcha_Image

Image 适配器使用生成的字符并解析为图像，并把它变换成难以自动解密。 它需要 » GD extension，使用 TrueType 或 Freetype 支持的编译。目前，Image 适配器只能产生 PNG 图像。

Zend_Captcha_Image 集成 Zend_Captcha_Word，并附加了下列方法：

  • setExpiration($expiration) 和 getExpiration() 指定 captcha 图像可以保留在文件系统 中的最大生命周期。一般长于会话的生命周期。每次调用 captcha 对象， 垃圾收集就运行一次，过期的图像就被清除。过期值以秒计。

  • setGcFreq($gcFreq) 和 getGcFreg() 指定垃圾收集运行的频度。每 1/$gcFreq 垃圾收集就运行一次（缺省值为 100）。

  • setFont($font) 和 getFont() 指定要用的字体。它是到字体文件的全路径。如果没有设置这个值，captcha 就在生成的时候抛出异常。字体是必需的。

  • setFontSize($fsize) 和 getFontSize() 指定字体尺寸，以象素为单位，用于生成 captcha。缺省值为 24px。

  • setHeight($height) 和 getHeight() 指定生成 captcha 图像的高度，以象素为单位。缺省值为 50px。

  • setWidth($width) 和 getWidth() 指定生成 captcha 图像的宽度，以象素为单位。缺省值为 200px 。

  • setImgDir($imgDir) 和 getImgDir() 指定 captcha 图像存储的目录。缺省为 "./images/captcha/" ，相对于引导（bootstrap）脚本。

  • setImgUrl($imgUrl) 和 getImgUrl() 指定用于 HTML 标记语言的 captcha 图像的相对路径。 缺省为 "/images/captcha/"。

  • setSuffix($suffix) 和 getSuffix() 指定文件名后缀。缺省为 ".png" 。注：它的改变不影响产生的图像类型。

所有上述选项都可作为选项传递给构造器，只要去掉 'set' 方法前缀并 把首字母变成小写：如 "suffix"、 "height"、"imgUrl" 等。

Zend_Captcha_ReCaptcha

ReCaptcha 适配器利用 Zend_Service_ReCaptcha 来生成校验 captchas。它有下列方法：

  • setPrivKey($key) 和 getPrivKey() 让你指定和 ReCaptcha 服务一起使用的私钥。这必需在构造期间指定，尽管任何时候它都可以被覆盖。

  • setPubKey($key) 和 getPubKey() 让你指定和 ReCaptcha 服务一起使用的公钥。这必需在构造期间指定，尽管任何时候它都可以被覆盖。

  • setService(Zend_Service_ReCaptcha $service) 和 getService() 让你指定并和 ReCaptcha 服务对象交互使用。

Captcha 操作
Zend_Captcha
Zend Framework手册 中文版
Zend_CodeGenerator
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Captcha
  • 简介
  • Captcha 操作
  • Captcha 适配器


Zend_CodeGenerator - Zend Framework Manual

Captcha 适配器
Zend Framework Reference
Zend Framework手册 中文版
Introduction

Zend_CodeGenerator

Table of Contents
  • Introduction
  • Zend_CodeGenerator Examples
  • Zend_CodeGenerator Reference
Captcha 适配器
Zend Framework Reference
Zend Framework手册 中文版
Introduction
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


Introduction - Zend Framework Manual

Zend_CodeGenerator
Zend_CodeGenerator
Zend Framework手册 中文版
Zend_CodeGenerator Examples

Introduction

Zend_CodeGenerator provides facilities to generate arbitrary code using an object oriented interface, both to create new code as well as to update existing code. While the current implementation is limited to generating PHP code, you can easily extend the base class in order to provide code generation for other tasks: JavaScript, configuration files, apache vhosts, etc.

Theory of Operation

In the most typical use case, you will simply instantiate a code generator class and either pass it the appropriate configuration or configure it after instantiation. To generate the code, you will simply echo the object or call its generate() method.

  1. // Passing configuration to the constructor:
  2. $file = new Zend_CodeGenerator_Php_File(array(
  3.     'classes' => array(
  4.         new Zend_CodeGenerator_Php_Class(array(
  5.             'name'    => 'World',
  6.             'methods' => array(
  7.                 new Zend_CodeGenerator_Php_Method(array(
  8.                     'name' => 'hello',
  9.                     'body' => 'echo \'Hello world!\';',
  10.                 )),
  11.             ),
  12.         )),
  13.     )
  14. ));
  15.
  16. // Configuring after instantiation
  17. $method = new Zend_CodeGenerator_Php_Method();
  18. $method->setName('hello')
  19.        ->setBody('echo \'Hello world!\';');
  20.
  21. $class = new Zend_CodeGenerator_Php_Class();
  22. $class->setName('World')
  23.       ->setMethod($method);
  24.
  25. $file = new Zend_CodeGenerator_Php_File();
  26. $file->setClass($class);
  27.
  28. // Render the generated file
  29. echo $file;
  30.
  31. // or write it to a file:
  32. file_put_contents('World.php', $file->generate());

Both of the above samples will render the same result:

  1. <?php
  2.
  3. class World
  4. {
  5.
  6.     public function hello()
  7.     {
  8.         echo 'Hello world!';
  9.     }
  10.
  11. }

Another common use case is to update existing code -- for instance, to add a method to a class. In such a case, you must first inspect the existing code using reflection, and then add your new method. Zend_CodeGenerator makes this trivially simple, by leveraging Zend_Reflection.

As an example, let's say we've saved the above to the file "World.php", and have already included it. We could then do the following:

  1. $class = Zend_CodeGenerator_Php_Class::fromReflection(
  2.     new Zend_Reflection_Class('World')
  3. );
  4.
  5. $method = new Zend_CodeGenerator_Php_Method();
  6. $method->setName('mrMcFeeley')
  7.        ->setBody('echo \'Hello, Mr. McFeeley!\';');
  8. $class->setMethod($method);
  9.
  10. $file = new Zend_CodeGenerator_Php_File();
  11. $file->setClass($class);
  12.
  13. // Render the generated file
  14. echo $file;
  15.
  16. // Or, better yet, write it back to the original file:
  17. file_put_contents('World.php', $file->generate());

The resulting class file will now look like this:

  1. <?php
  2.
  3. class World
  4. {
  5.
  6.     public function hello()
  7.     {
  8.         echo 'Hello world!';
  9.     }
  10.
  11.     public function mrMcFeeley()
  12.     {
  13.         echo 'Hellow Mr. McFeeley!';
  14.     }
  15.
  16. }
Zend_CodeGenerator
Zend_CodeGenerator
Zend Framework手册 中文版
Zend_CodeGenerator Examples
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_CodeGenerator
  • Introduction
  • Zend_CodeGenerator Examples
  • Zend_CodeGenerator Reference


Zend_CodeGenerator Examples - Zend Framework Manual

Introduction
Zend_CodeGenerator
Zend Framework手册 中文版
Zend_CodeGenerator Reference

Zend_CodeGenerator Examples

Example #1 Generating PHP classes

The following example generates an empty class with a class-level DocBlock.

  1. $foo      = new Zend_CodeGenerator_Php_Class();
  2. $docblock = new Zend_CodeGenerator_Php_Docblock(array(
  3.     'shortDescription' => 'Sample generated class',
  4.     'longDescription'  => 'This is a class generated with Zend_CodeGenerator.',
  5.     'tags'             => array(
  6.         array(
  7.             'name'        => 'version',
  8.             'description' => '$Rev:$',
  9.         ),
  10.         array(
  11.             'name'        => 'license',
  12.             'description' => 'New BSD',
  13.         ),
  14.     ),
  15. ));
  16. $foo->setName('Foo')
  17.     ->setDocblock($docblock);
  18. echo $foo->generate();

The above code will result in the following:

  1. /**
  2. * Sample generated class
  3. *
  4. * This is a class generated with Zend_CodeGenerator.
  5. *
  6. * @version $Rev:$
  7. * @license New BSD
  8. *
  9. */
  10. class Foo
  11. {
  12.
  13. }

Example #2 Generating PHP classes with class properties

Building on the previous example, we now add properties to our generated class.

  1. $foo      = new Zend_CodeGenerator_Php_Class();
  2. $docblock = new Zend_CodeGenerator_Php_Docblock(array(
  3.     'shortDescription' => 'Sample generated class',
  4.     'longDescription'  => 'This is a class generated with Zend_CodeGenerator.',
  5.     'tags'             => array(
  6.         array(
  7.             'name'        => 'version',
  8.             'description' => '$Rev:$',
  9.         ),
  10.         array(
  11.             'name'        => 'license',
  12.             'description' => 'New BSD',
  13.         ),
  14.     ),
  15. ));
  16. $foo->setName('Foo')
  17.     ->setDocblock($docblock)
  18.     ->setProperties(array(
  19.         array(
  20.             'name'         => '_bar',
  21.             'visibility'   => 'protected',
  22.             'defaultValue' => 'baz',
  23.         ),
  24.         array(
  25.             'name'         => 'baz',
  26.             'visibility'   => 'public',
  27.             'defaultValue' => 'bat',
  28.         ),
  29.         array(
  30.             'name'         => 'bat',
  31.             'const'        => true,
  32.             'defaultValue' => 'foobarbazbat',
  33.         ),
  34.     ));
  35. echo $foo->generate();

The above results in the following class definition:

  1. /**
  2. * Sample generated class
  3. *
  4. * This is a class generated with Zend_CodeGenerator.
  5. *
  6. * @version $Rev:$
  7. * @license New BSD
  8. *
  9. */
  10. class Foo
  11. {
  12.
  13.     protected $_bar = 'baz';
  14.
  15.     public $baz = 'bat';
  16.
  17.     const bat = 'foobarbazbat';
  18.
  19. }

Example #3 Generating PHP classes with class methods

Zend_CodeGenerator_Php_Class allows you to attach methods with optional content to your classes. Methods may be attached as either arrays or concrete Zend_CodeGenerator_Php_Method instances.

  1. $foo      = new Zend_CodeGenerator_Php_Class();
  2. $docblock = new Zend_CodeGenerator_Php_Docblock(array(
  3.     'shortDescription' => 'Sample generated class',
  4.     'longDescription'  => 'This is a class generated with Zend_CodeGenerator.',
  5.     'tags'             => array(
  6.         array(
  7.             'name'        => 'version',
  8.             'description' => '$Rev:$',
  9.         ),
  10.         array(
  11.             'name'        => 'license',
  12.             'description' => 'New BSD',
  13.         ),
  14.     ),
  15. ));
  16. $foo->setName('Foo')
  17.     ->setDocblock($docblock)
  18.     ->setProperties(array(
  19.         array(
  20.             'name'         => '_bar',
  21.             'visibility'   => 'protected',
  22.             'defaultValue' => 'baz',
  23.         ),
  24.         array(
  25.             'name'         => 'baz',
  26.             'visibility'   => 'public',
  27.             'defaultValue' => 'bat',
  28.         ),
  29.         array(
  30.             'name'         => 'bat',
  31.             'const'        => true,
  32.             'defaultValue' => 'foobarbazbat',
  33.         ),
  34.     ))
  35.     ->setMethods(array(
  36.         // Method passed as array
  37.         array(
  38.             'name'       => 'setBar',
  39.             'parameters' => array(
  40.                 array('name' => 'bar'),
  41.             ),
  42.             'body'       => '$this->_bar = $bar;' . "\n" . 'return $this;',
  43.             'docblock'   => new Zend_CodeGenerator_Php_Docblock(array(
  44.                 'shortDescription' => 'Set the bar property',
  45.                 'tags'             => array(
  46.                     new Zend_CodeGenerator_Php_Docblock_Tag_Param(array(
  47.                         'paramName' => 'bar',
  48.                         'datatype'  => 'string'
  49.                     )),
  50.                     new Zend_CodeGenerator_Php_Docblock_Tag_Return(array(
  51.                         'datatype'  => 'string',
  52.                     )),
  53.                 ),
  54.             )),
  55.         ),
  56.         // Method passed as concrete instance
  57.         new Zend_CodeGenerator_Php_Method(array(
  58.             'name' => 'getBar',
  59.             'body'       => 'return $this->_bar;',
  60.             'docblock'   => new Zend_CodeGenerator_Php_Docblock(array(
  61.                 'shortDescription' => 'Retrieve the bar property',
  62.                 'tags'             => array(
  63.                     new Zend_CodeGenerator_Php_Docblock_Tag_Return(array(
  64.                         'datatype'  => 'string|null',
  65.                     )),
  66.                 ),
  67.             )),
  68.         )),
  69.     ));
  70.
  71. echo $foo->generate();

The above generates the following output:

  1. /**
  2. * Sample generated class
  3. *
  4. * This is a class generated with Zend_CodeGenerator.
  5. *
  6. * @version $Rev:$
  7. * @license New BSD
  8. */
  9. class Foo
  10. {
  11.
  12.     protected $_bar = 'baz';
  13.
  14.     public $baz = 'bat';
  15.
  16.     const bat = 'foobarbazbat';
  17.
  18.     /**
  19.      * Set the bar property
  20.      *
  21.      * @param string bar
  22.      * @return string
  23.      */
  24.     public function setBar($bar)
  25.     {
  26.         $this->_bar = $bar;
  27.         return $this;
  28.     }
  29.
  30.     /**
  31.      * Retrieve the bar property
  32.      *
  33.      * @return string|null
  34.      */
  35.     public function getBar()
  36.     {
  37.         return $this->_bar;
  38.     }
  39.
  40. }

Example #4 Generating PHP files

Zend_CodeGenerator_Php_File can be used to generate the contents of a PHP file. You can include classes as well as arbitrary content body. When attaching classes, you should attach either concrete Zend_CodeGenerator_Php_Class instances or an array defining the class.

In the example below, we will assume you've defined $foo per one of the class definitions in a previous example.

  1. $file = new Zend_CodeGenerator_Php_File(array(
  2.     'classes'  => array($foo);
  3.     'docblock' => new Zend_CodeGenerator_Php_Docblock(array(
  4.         'shortDescription' => 'Foo class file',
  5.         'tags'             => array(
  6.             array(
  7.                 'name'        => 'license',
  8.                 'description' => 'New BSD',
  9.             ),
  10.         ),
  11.     )),
  12.     'body'     => 'define(\'APPLICATION_ENV\', \'testing\');',
  13. ));

Calling generate() will generate the code -- but not write it to a file. You will need to capture the contents and write them to a file yourself. As an example:

  1. $code = $file->generate();
  2. file_put_contents('Foo.php', $code);

The above will generate the following file:

  1. <?php
  2. /**
  3. * Foo class file
  4. *
  5. * @license New BSD
  6. */
  7.
  8. /**
  9. * Sample generated class
  10. *
  11. * This is a class generated with Zend_CodeGenerator.
  12. *
  13. * @version $Rev:$
  14. * @license New BSD
  15. */
  16. class Foo
  17. {
  18.
  19.     protected $_bar = 'baz';
  20.
  21.     public $baz = 'bat';
  22.
  23.     const bat = 'foobarbazbat';
  24.
  25.     /**
  26.      * Set the bar property
  27.      *
  28.      * @param string bar
  29.      * @return string
  30.      */
  31.     public function setBar($bar)
  32.     {
  33.         $this->_bar = $bar;
  34.         return $this;
  35.     }
  36.
  37.     /**
  38.      * Retrieve the bar property
  39.      *
  40.      * @return string|null
  41.      */
  42.     public function getBar()
  43.     {
  44.         return $this->_bar;
  45.     }
  46.
  47. }
  48.
  49. define('APPLICATION_ENV', 'testing');

Example #5 Seeding PHP file code generation via reflection

You can add PHP code to an existing PHP file using the code generator. To do so, you need to first do reflection on it. The static method fromReflectedFileName() allows you to do this.

  1. $generator = Zend_CodeGenerator_Php_File::fromReflectedFileName($path);
  2. $body = $generator->getBody();
  3. $body .= "\n\$foo->bar();";
  4. file_put_contents($path, $generator->generate());

Example #6 Seeding PHP class generation via reflection

You may add code to an existing class. To do so, first use the static fromReflection() method to map the class into a generator object. From there, you may add additional properties or methods, and then regenerate the class.

  1. $generator = Zend_CodeGenerator_Php_Class::fromReflection(
  2.     new Zend_Reflection_Class($class)
  3. );
  4. $generator->setMethod(array(
  5.     'name'       => 'setBaz',
  6.     'parameters' => array(
  7.         array('name' => 'baz'),
  8.     ),
  9.     'body'       => '$this->_baz = $baz;' . "\n" . 'return $this;',
  10.     'docblock'   => new Zend_CodeGenerator_Php_Docblock(array(
  11.         'shortDescription' => 'Set the baz property',
  12.         'tags'             => array(
  13.             new Zend_CodeGenerator_Php_Docblock_Tag_Param(array(
  14.                 'paramName' => 'baz',
  15.                 'datatype'  => 'string'
  16.             )),
  17.             new Zend_CodeGenerator_Php_Docblock_Tag_Return(array(
  18.                 'datatype'  => 'string',
  19.             )),
  20.         ),
  21.     )),
  22. ));
  23. $code = $generator->generate();
Introduction
Zend_CodeGenerator
Zend Framework手册 中文版
Zend_CodeGenerator Reference
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_CodeGenerator
  • Introduction
  • Zend_CodeGenerator Examples
  • Zend_CodeGenerator Reference


Zend_CodeGenerator Reference - Zend Framework Manual

Zend_CodeGenerator Examples
Zend_CodeGenerator
Zend Framework手册 中文版
Zend_Config

Zend_CodeGenerator Reference

Abstract Classes and Interfaces

Zend_CodeGenerator_Abstract

The base class from which all CodeGenerator classes inherit provides the minimal functionality necessary. It's API is as follows:

  1. abstract class Zend_CodeGenerator_Abstract
  2. {
  3.     final public function __construct(Array $options = array())
  4.     public function setOptions(Array $options)
  5.     public function setSourceContent($sourceContent)
  6.     public function getSourceContent()
  7.     protected function _init()
  8.     protected function _prepare()
  9.     abstract public function generate();
  10.     final public function __toString()
  11. }

The constructor first calls _init() (which is left empty for the concrete extending class to implement), then passes the $options parameter to setOptions(), and finally calls _prepare() (again, to be implemented by an extending class).

Like most classes in Zend Framework, setOptions() compares an option key to existing setters in the class, and passes the value on to that method if found.

__toString() is marked as final, and proxies to generate().

setSourceContent() and getSourceContent() are intended to either set the default content for the code being generated, or to replace said content once all generation tasks are complete.

Zend_CodeGenerator_Php_Abstract

Zend_CodeGenerator_Php_Abstract extends Zend_CodeGenerator_Abstract, and adds some properties for tracking whether content has changed as well as the amount of indentation that should appear before generated content. Its API is as follows:

  1. abstract class Zend_CodeGenerator_Php_Abstract
  2.     extends Zend_CodeGenerator_Abstract
  3. {
  4.     public function setSourceDirty($isSourceDirty = true)
  5.     public function isSourceDirty()
  6.     public function setIndentation($indentation)
  7.     public function getIndentation()
  8. }

Zend_CodeGenerator_Php_Member_Abstract

Zend_CodeGenerator_Php_Member_Abstract is a base class for generating class members -- properties and methods -- and provides accessors and mutators for establishing visibility; whether or not the member is abstract, static, or final; and the name of the member. Its API is as follows:

  1. abstract class Zend_CodeGenerator_Php_Member_Abstract
  2.     extends Zend_CodeGenerator_Php_Abstract
  3. {
  4.     public function setAbstract($isAbstract)
  5.     public function isAbstract()
  6.     public function setStatic($isStatic)
  7.     public function isStatic()
  8.     public function setVisibility($visibility)
  9.     public function getVisibility()
  10.     public function setName($name)
  11.     public function getName()
  12. }

Concrete CodeGenerator Classes

Zend_CodeGenerator_Php_Body

Zend_CodeGenerator_Php_Body is intended for generating arbitrary procedural code to include within a file. As such, you simply set content for the object, and it will return that content when you invoke generate().

The API of the class is as follows:

  1. class Zend_CodeGenerator_Php_Body extends Zend_CodeGenerator_Php_Abstract
  2. {
  3.     public function setContent($content)
  4.     public function getContent()
  5.     public function generate()
  6. }

Zend_CodeGenerator_Php_Class

Zend_CodeGenerator_Php_Class is intended for generating PHP classes. The basic functionality just generates the PHP class itself, as well as optionally the related PHP DocBlock. Classes may implement or inherit from other classes, and may be marked as abstract. Utilizing other code generator classes, you can also attach class constants, properties, and methods.

The API is as follows:

  1. class Zend_CodeGenerator_Php_Class extends Zend_CodeGenerator_Php_Abstract
  2. {
  3.     public static function fromReflection(
  4.         Zend_Reflection_Class $reflectionClass
  5.     )
  6.     public function setDocblock(Zend_CodeGenerator_Php_Docblock $docblock)
  7.     public function getDocblock()
  8.     public function setName($name)
  9.     public function getName()
  10.     public function setAbstract($isAbstract)
  11.     public function isAbstract()
  12.     public function setExtendedClass($extendedClass)
  13.     public function getExtendedClass()
  14.     public function setImplementedInterfaces(Array $implementedInterfaces)
  15.     public function getImplementedInterfaces()
  16.     public function setProperties(Array $properties)
  17.     public function setProperty($property)
  18.     public function getProperties()
  19.     public function getProperty($propertyName)
  20.     public function setMethods(Array $methods)
  21.     public function setMethod($method)
  22.     public function getMethods()
  23.     public function getMethod($methodName)
  24.     public function hasMethod($methodName)
  25.     public function isSourceDirty()
  26.     public function generate()
  27. }

The setProperty() method accepts an array of information that may be used to generate a Zend_CodeGenerator_Php_Property instance -- or simply an instance of Zend_CodeGenerator_Php_Property. Likewise, setMethod() accepts either an array of information for generating a Zend_CodeGenerator_Php_Method instance or a concrete instance of that class.

Note that setDocBlock() expects an instance of Zend_CodeGenerator_Php_DocBlock.

Zend_CodeGenerator_Php_Docblock

Zend_CodeGenerator_Php_Docblock can be used to generate arbitrary PHP docblocks, including all the standard docblock features: short and long descriptions and annotation tags.

Annotation tags may be set using the setTag() and setTags() methods; these each take either an array describing the tag that may be passed to the Zend_CodeGenerator_Php_Docblock_Tag constructor, or an instance of that class.

The API is as follows:

  1. class Zend_CodeGenerator_Php_Docblock extends Zend_CodeGenerator_Php_Abstract
  2. {
  3.     public static function fromReflection(
  4.         Zend_Reflection_Docblock $reflectionDocblock
  5.     )
  6.     public function setShortDescription($shortDescription)
  7.     public function getShortDescription()
  8.     public function setLongDescription($longDescription)
  9.     public function getLongDescription()
  10.     public function setTags(Array $tags)
  11.     public function setTag($tag)
  12.     public function getTags()
  13.     public function generate()
  14. }

Zend_CodeGenerator_Php_Docblock_Tag

Zend_CodeGenerator_Php_Docblock_Tag is intended for creating arbitrary annotation tags for inclusion in PHP docblocks. Tags are expected to contain a name (the portion immediately following the '@' symbol) and a description (everything following the tag name).

The class API is as follows:

  1. class Zend_CodeGenerator_Php_Docblock_Tag
  2.     extends Zend_CodeGenerator_Php_Abstract
  3. {
  4.     public static function fromReflection(
  5.         Zend_Reflection_Docblock_Tag $reflectionTag
  6.     )
  7.     public function setName($name)
  8.     public function getName()
  9.     public function setDescription($description)
  10.     public function getDescription()
  11.     public function generate()
  12. }

Zend_CodeGenerator_Php_DocBlock_Tag_Param

Zend_CodeGenerator_Php_DocBlock_Tag_Param is a specialized version of Zend_CodeGenerator_Php_DocBlock_Tag, and represents a method parameter. The tag name is therefor known ("param"), but due to the format of this annotation tag, additional information is required in order to generate it: the parameter name and data type it represents.

The class API is as follows:

  1. class Zend_CodeGenerator_Php_Docblock_Tag_Param
  2.     extends Zend_CodeGenerator_Php_Docblock_Tag
  3. {
  4.     public static function fromReflection(
  5.         Zend_Reflection_Docblock_Tag $reflectionTagParam
  6.     )
  7.     public function setDatatype($datatype)
  8.     public function getDatatype()
  9.     public function setParamName($paramName)
  10.     public function getParamName()
  11.     public function generate()
  12. }

Zend_CodeGenerator_Php_DocBlock_Tag_Return

Like the param docblock tag variant, Zend_CodeGenerator_Php_Docblock_Tab_Return is an annotation tag variant for representing a method return value. In this case, the annotation tag name is known ("return"), but requires a return type.

The class API is as follows:

  1. class Zend_CodeGenerator_Php_Docblock_Tag_Param
  2.     extends Zend_CodeGenerator_Php_Docblock_Tag
  3. {
  4.     public static function fromReflection(
  5.         Zend_Reflection_Docblock_Tag $reflectionTagReturn
  6.     )
  7.     public function setDatatype($datatype)
  8.     public function getDatatype()
  9.     public function generate()
  10. }

Zend_CodeGenerator_Php_File

Zend_CodeGenerator_Php_File is used to generate the full contents of a file that will contain PHP code. The file may contain classes or arbitrary PHP code, as well as a file-level docblock if desired.

When adding classes to the file, you will need to pass either an array of information to pass to the Zend_CodeGenerator_Php_Class constructor, or an instance of that class. Similarly, with docblocks, you will need to pass information for the Zend_CodeGenerator_Php_Docblock constructor to consume or an instance of the class.

The API of the class is as follows:

  1. class Zend_CodeGenerator_Php_File extends Zend_CodeGenerator_Php_Abstract
  2. {
  3.     public static function fromReflectedFilePath(
  4.         $filePath,
  5.         $usePreviousCodeGeneratorIfItExists = true,
  6.         $includeIfNotAlreadyIncluded = true)
  7.     public static function fromReflection(Zend_Reflection_File $reflectionFile)
  8.     public function setDocblock(Zend_CodeGenerator_Php_Docblock $docblock)
  9.     public function getDocblock()
  10.     public function setRequiredFiles($requiredFiles)
  11.     public function getRequiredFiles()
  12.     public function setClasses(Array $classes)
  13.     public function getClass($name = null)
  14.     public function setClass($class)
  15.     public function setFilename($filename)
  16.     public function getFilename()
  17.     public function getClasses()
  18.     public function setBody($body)
  19.     public function getBody()
  20.     public function isSourceDirty()
  21.     public function generate()
  22. }

Zend_CodeGenerator_Php_Member_Container

Zend_CodeGenerator_Php_Member_Container is used internally by Zend_CodeGenerator_Php_Class to keep track of class members -- properties and methods alike. These are indexed by name, using the concrete instances of the members as values.

The API of the class is as follows:

  1. class Zend_CodeGenerator_Php_Member_Container extends ArrayObject
  2. {
  3.     public function __construct($type = self::TYPE_PROPERTY)
  4. }

Zend_CodeGenerator_Php_Method

Zend_CodeGenerator_Php_Method describes a class method, and can generate both the code and the docblock for the method. The visibility and status as static, abstract, or final may be indicated, per its parent class, Zend_CodeGenerator_Php_Member_Abstract. Finally, the parameters and return value for the method may be specified.

Parameters may be set using setParameter() or setParameters(). In each case, a parameter should either be an array of information to pass to the Zend_CodeGenerator_Php_Parameter constructor or an instance of that class.

The API of the class is as follows:

  1. class Zend_CodeGenerator_Php_Method
  2.     extends Zend_CodeGenerator_Php_Member_Abstract
  3. {
  4.     public static function fromReflection(
  5.         Zend_Reflection_Method $reflectionMethod
  6.     )
  7.     public function setDocblock(Zend_CodeGenerator_Php_Docblock $docblock)
  8.     public function getDocblock()
  9.     public function setFinal($isFinal)
  10.     public function setParameters(Array $parameters)
  11.     public function setParameter($parameter)
  12.     public function getParameters()
  13.     public function setBody($body)
  14.     public function getBody()
  15.     public function generate()
  16. }

Zend_CodeGenerator_Php_Parameter

Zend_CodeGenerator_Php_Parameter may be used to specify method parameters. Each parameter may have a position (if unspecified, the order in which they are registered with the method will be used), a default value, and a data type; a parameter name is required.

The API of the class is as follows:

  1. class Zend_CodeGenerator_Php_Parameter extends Zend_CodeGenerator_Php_Abstract
  2. {
  3.     public static function fromReflection(
  4.         Zend_Reflection_Parameter $reflectionParameter
  5.     )
  6.     public function setType($type)
  7.     public function getType()
  8.     public function setName($name)
  9.     public function getName()
  10.     public function setDefaultValue($defaultValue)
  11.     public function getDefaultValue()
  12.     public function setPosition($position)
  13.     public function getPosition()
  14.     public function getPassedByReference()
  15.     public function setPassedByReference($passedByReference)
  16.     public function generate()
  17. }

There are several problems that might occur when trying to set NULL, booleans or arrays as default values. For this the value holder object Zend_CodeGenerator_Php_ParameterDefaultValue can be used, for example:

  1. $parameter = new Zend_CodeGenerator_Php_Parameter();
  2. $parameter->setDefaultValue(
  3.     new Zend_CodeGenerator_Php_Parameter_DefaultValue("null")
  4. );
  5. $parameter->setDefaultValue(
  6.     new Zend_CodeGenerator_Php_Parameter_DefaultValue("array('foo', 'bar')")
  7. );

Internally setDefaultValue() also converts the values which can't be expressed in PHP into the value holder.

Zend_CodeGenerator_Php_Property

Zend_CodeGenerator_Php_Property describes a class property, which may be either a constant or a variable. In each case, the property may have an optional default value associated with it. Additionally, the visibility of variable properties may be set, per the parent class, Zend_CodeGenerator_Php_Member_Abstract.

The API of the class is as follows:

  1. class Zend_CodeGenerator_Php_Property
  2.     extends Zend_CodeGenerator_Php_Member_Abstract
  3. {
  4.     public static function fromReflection(
  5.         Zend_Reflection_Property $reflectionProperty
  6.     )
  7.     public function setConst($const)
  8.     public function isConst()
  9.     public function setDefaultValue($defaultValue)
  10.     public function getDefaultValue()
  11.     public function generate()
  12. }
Zend_CodeGenerator Examples
Zend_CodeGenerator
Zend Framework手册 中文版
Zend_Config
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_CodeGenerator
  • Introduction
  • Zend_CodeGenerator Examples
  • Zend_CodeGenerator Reference


Zend_Config - Zend Framework Manual

Zend_CodeGenerator Reference
Zend Framework Reference
Zend Framework手册 中文版
简介

Zend_Config

Table of Contents
  • 简介
  • 操作理论
  • Zend_Config_Ini
  • Zend_Config_Xml
Zend_CodeGenerator Reference
Zend Framework Reference
Zend Framework手册 中文版
简介
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


简介 - Zend Framework Manual

Zend_Config
Zend_Config
Zend Framework手册 中文版
操作理论

简介

Zend_Config被设计在应用程序中简化访问和使用配置数据。它为在应用程序代码中访问这样的配置数据提供了一个基于用户接口的嵌入式对象属性。配置数据可能来自于各种支持等级结构数据存储的媒体。当前Zend_Config为存储在Zend_Config_Ini 和Zend_Config_Xml的文本文件中的配置数据提供了适配器。

Example #1 使用 Zend_Config 本身

通常用户可以使用象Zend_Config_Ini 或 Zend_Config_Xml适配器类的其中之一，但如果配置数据在PHP数组里可用，为了使用一个简单的面向对象的接口，可以简单地传递数据到Zend_Config构造器：

// 给出一个配置数据的数组
$configArray = array(
    'webhost'  => 'www.example.com',
    'database' => array(
        'adapter' => 'pdo_mysql',
        'params'  => array(
            'host'     => 'db.example.com',
            'username' => 'dbuser',
            'password' => 'secret',
            'dbname'   => 'mydatabase'
        )
    )
);

// 基于配置数据创建面向对象的 wrapper
$config = new Zend_Config($configArray);

// 输出配置数据 (结果在'www.example.com'中)
echo $config->webhost;

// 使用配置数据来连接数据库
$db = Zend_Db::factory($config->database->adapter,
                       $config->database->params->toArray());

// 另外的用法：简单地传递 Zend_Config 对象。
// Zend_Db factory 知道如何翻译它。
$db = Zend_Db::factory($config->database);

如上例所示，Zend_Config 提供嵌套的对象属性语句来访问传递给它的构造器的配置数据。

连同面向对象访问数据值，Zend_Config也有get()方法，如果数据元素不存在，它将返回提供的缺省值，例如：

$host = $config->database->get('host', 'localhost');

Example #2 Using Zend_Config with a PHP Configuration File

It is often desirable to use a pure PHP-based configuration file. The following code illustrates how easily this can be accomplished:

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

// Configuration consumption
$config = new Zend_Config(require 'config.php');

// Print a configuration datum (results in 'www.example.com')
echo $config->webhost;
Zend_Config
Zend_Config
Zend Framework手册 中文版
操作理论
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Config
  • 简介
  • 操作理论
  • Zend_Config_Ini
  • Zend_Config_Xml


操作理论 - Zend Framework Manual

简介
Zend_Config
Zend Framework手册 中文版
Zend_Config_Ini

操作理论

配置数据在Zend_Config构造器通过关联数组(associative arrary)可访问，为了支持从通用到特殊组织数据，它可以是多维的。具体的适配器类函数为Zend_Config的构造器从存储到处理关联数组来适应配置数据。用户脚本可以直接提供这样的数组给Zend_Config构造器，不需要使用适配器类，因为它可以很好地工作在特定的情形下。

为了很容易简单地访问配置数据，Zend_Config实现了Countable 和 Iterator 接口。这样，可以基于Zend_Config对象使用» count()函数和PHP语句如» foreach。

缺省地，配置数据通过Zend_Config可用是只读的，并且赋值（例如， $config->database->host = 'example.com'）导致抛出异常。这个缺省的行为可以通过构造器重载，然而，需要允许修改数据值。并且，当修改被允许时，Zend_Config支持未设定的值（例如 unset($config->database->host);）。

Note: 不要混淆如在内存中更改和保存配置数据到指定的存储媒体很重要。创建和更改配置数据给不同的存储媒体的工具超出了Zend_Config的范围。为创建和更改配置数据给不同的存储媒体的第三方开源方案很容易实现。

适配器类从Zend_Config类继承，因为它们使用它的函数。

Zend_Config函数家族把配置数据组织成节（section）。Zend_Config适配器对象可以带一个指定的节加载，或者带有多个指定的节，或者所有节（如果没有指定）。

Zend_Config适配器类支持单继承模型，它允许配置数据从一个节到另一个节被继承，这是为了为不同目的而减少或消除复制配置数据而提供的。一个继承的节也可以重写从父节继承过来的值。象PHP类继承，一个节可以从一个父节继承，这个父节可能是从祖父节继承的，等等，但是多重继承（例如，节C直接从父节A和B继承）不被支持。

如果你有两个Zend_Config对象，你可以用merge()函数把它们合并成一个单个的对象。例如，对$config和$localConfig，使用$config->merge($localConfig);，你可以把数据从$localConfig合并到$config。在$localConfig中的条目将覆盖在$config中同名的条目。

简介
Zend_Config
Zend Framework手册 中文版
Zend_Config_Ini
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Config
  • 简介
  • 操作理论
  • Zend_Config_Ini
  • Zend_Config_Xml


Zend_Config_Ini - Zend Framework Manual

操作理论
Zend_Config
Zend Framework手册 中文版
Zend_Config_Xml

Zend_Config_Ini

Zend_Config_Ini允许开发者通过嵌套的对象属性语法在应用程序中用熟悉的 INI 格式存储和读取配置数据。INI 格式在提供拥有配置数据键的等级结构和配置数据节之间的继承能力方面具有专长。配置数据等级结构通过用点或者句号 (.)分离键值。一个节可以扩展或者通过在节的名称之后带一个冒号(:)和被继承的配置数据的节的名称来从另一个节继承。

Note: parse_ini_file
 Zend_Config_Ini 使用» parse_ini_file()PHP 函数。请复习这个文档了解它的特定行为，它在Zend_Config_Ini中使用，例如true, false, yes, no 和 null 这些特殊的值如何操作。

Note: 键分离器
 缺省地，键分离器字符是句号(.)。然而，这个可以通过当构造Zend_Config_Ini对象时修改$options key 'nestSeparator' 被修改。例如：

$options['nestSeparator'] = ':';
$config = new Zend_Config_Ini('/path/to/config.ini',
                              'staging',
                              $options);

Example #1 使用 Zend_Config_Ini

这个例子示例了从 INI 文件加载配置数据的Zend_Config_Ini的基本用法。在这个例子中有生产系统（production system）和开发系统（staging system）的配置数据。因为开发系统配置数据和生产系统的配置数据类似，所以开发系统的节从生产系统的节继承。在这个案例中，结果(decision)是任意的并且它可以反过来做，即生产系统节从开发系统节继承，尽管这不可能用于更复杂的情形。接着，假定下面的配置数据包含在/path/to/config.ini中：

; 生产站点配置数据
[production]
webhost                  = www.example.com
database.adapter         = pdo_mysql
database.params.host     = db.example.com
database.params.username = dbuser
database.params.password = secret
database.params.dbname   = dbname

; 开发站点配置数据从生产站点配置数据集成并如果需要可以重写
[staging : production]
database.params.host     = dev.example.com
database.params.username = devuser
database.params.password = devsecret

接着，假定开发者需要从INI文件取开发配置数据。这非常简单，只要指定INI文件和开发系统节就可以加载这些数据了：

$config = new Zend_Config_Ini('/path/to/config.ini', 'staging');

echo $config->database->params->host;   // 输出 "dev.example.com"
echo $config->database->params->dbname; // 输出 "dbname"

Note:

Zend_Config_Ini 构造器参数
参数 | 注释
$filename | 要加载的 INI 文件。
$section | 在INI文件中 [section] （节）将被加载。把这个参数设置为null，所有的节将被加载。另外，一个节名称的数组被提供给加载多个节。
$options = false 选项数组。下面的键被支持：

  • allowModifications：设置为true 允许随后加载文件更改。缺省为false

  • nestSeparator: 设置嵌套字符。缺省为"."

操作理论
Zend_Config
Zend Framework手册 中文版
Zend_Config_Xml
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Config
  • 简介
  • 操作理论
  • Zend_Config_Ini
  • Zend_Config_Xml


Zend_Config_Xml - Zend Framework Manual

Zend_Config_Ini
Zend_Config
Zend Framework手册 中文版
Zend_Config_Writer

Zend_Config_Xml

Zend_Config_Xml 让开发者能够存储配置数据到一个简单XML格式并通过嵌入对象属性语法来读取。XML文件的根元素（root element）不相关并可以任意命名。顶级的XML元素和配置数据的节相对应。XML格式通过嵌入XML元素到节一级元素（section-level elements）的下面来支持等级结构组织。叶一级（leaf-level）的XML元素和配置数据的值相对应。节继承通过一个特殊的XML属性名为extends来支持，与之相对应的这个属性的值通过扩展节（extending section）来继承。

Note: 返回类型
 读入Zend_Config_Xml中的配置数据总是返回字串。数据从字符串到其它类型的转换留给开发者来适应他们特定的需求。

Example #1 使用Zend_Config_Xml

这个例子示例了从INI文件加载配置数据的Zend_Config_Xml的基本用法。在这个例子中有生产系统（production system）和开发系统（staging system）的配置数据。因为开发系统配置数据和生产系统的配置数据类似，所以开发系统的节从生产系统的节继承。在这个案例中，结果(decision)是任意的并且它可以反过来做，即生产系统节从开发系统节继承，尽管这不可能用于更复杂的情形。接着，假定下面的配置数据包含在/path/to/config.xml中：

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

接着，假定开发者需要从XML文件取开发配置数据。这非常简单，只要指定XML文件和开发系统节就可以加载这些数据了：

$config = new Zend_Config_Xml('/path/to/config.xml', 'staging');

echo $config->database->params->host;   // 输出 "dev.example.com"
echo $config->database->params->dbname; // 输出 "dbname"

Example #2 在 Zend_Config_Xml 使用标签（tag）属性

Zend_Config_Xml 也支持另外两种方法在配置文件里定义节点。它们都利用属性。 因为 extends 和 value 属性是保留关键字（后者是第二种使用属性的方法），它们可能不被使用。 第一种方法使用属性是把属性添加到父节点，它本身就变成了子节点：

<?xml version="1.0"?>
<configdata>
    <production webhost="www.example.com">
        <database adapter="pdo_mysql">
            <params host="db.example.com" username="dbuser" password="secret" dbname="dbname"/>
        </database>
    </production>
    <staging extends="production">
        <database>
            <params host="dev.example.com" username="devuser" password="devsecret"/>
        </database>
    </staging>
</configdata>

另一种方法也不会使配置文件变小，但使维护变得容易，是因为你需要要写标签名两次。你可以创建一个空标签，它在 value 属性里包含它的值：

<?xml version="1.0"?>
<configdata>
    <production>
        <webhost>www.example.com</webhost>
        <database>
            <adapter value="pdo_mysql"/>
            <params>
                <host value="db.example.com"/>
                <username value="dbuser"/>
                <password value="secret"/>
                <dbname value="dbname"/>
            </params>
        </database>
    </production>
    <staging extends="production">
        <database>
            <params>
                <host value="dev.example.com"/>
                <username value="devuser"/>
                <password value="devsecret"/>
            </params>
        </database>
    </staging>
</configdata>
Zend_Config_Ini
Zend_Config
Zend Framework手册 中文版
Zend_Config_Writer
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Config
  • 简介
  • 操作理论
  • Zend_Config_Ini
  • Zend_Config_Xml


Zend_Config_Writer - Zend Framework Manual

Zend_Config_Writer
Zend_Config_Writer
Zend Framework手册 中文版
Zend_Console_Getopt

Zend_Config_Writer

Zend_Config_Writer gives you the ability to write config files out of Zend_Config objects. It works with an adapter-less system and thus is very easy to use. By default Zend_Config_Writer ships with three adapters, which are all file-based. You instantiate a writer with specific options, which can be filename and config. Then you call the write() method of the writer and the config file is created. You can also give $filename and $config directly to the write() method. Currently the following writers are shipped with Zend_Config_Writer:

  • Zend_Config_Writer_Array

  • Zend_Config_Writer_Ini

  • Zend_Config_Writer_Xml

The INI writer has two modes for rendering with regard to sections. By default the top-level configuration is always written into section names. By calling $writer->setRenderWithoutSections(); all options are written into the global namespace of the INI file and no sections are applied.

As an addition Zend_Config_Writer_Ini has an additional option parameter nestSeparator, which defines with which character the single nodes are separated. The default is a single dot, like it is accepted by Zend_Config_Ini by default.

When modifying or creating a Zend_Config object, there are some things to know. To create or modify a value, you simply say set the parameter of the Zend_Config object via the parameter accessor (->). To create a section in the root or to create a branch, you just create a new array ("$config->branch = array();"). To define which section extends another one, you call the setExtend() method on the root Zend_Config object.

Example #1 Using Zend_Config_Writer

This example illustrates the basic use of Zend_Config_Writer_Xml to create a new config file:

  1. // Create the config object
  2. $config = new Zend_Config(array(), true);
  3. $config->production = array();
  4. $config->staging    = array();
  5.
  6. $config->setExtend('staging', 'production');
  7.
  8. $config->production->db = array();
  9. $config->production->db->hostname = 'localhost';
  10. $config->production->db->username = 'production';
  11.
  12. $config->staging->db = array();
  13. $config->staging->db->username = 'staging';
  14.
  15. // Write the config file in one of the following ways:
  16. // a)
  17. $writer = new Zend_Config_Writer_Xml(array('config'   => $config,
  18.                                            'filename' => 'config.xml'));
  19. $writer->write();
  20.
  21. // b)
  22. $writer = new Zend_Config_Writer_Xml();
  23. $writer->setConfig($config)
  24.        ->setFilename('config.xml')
  25.        ->write();
  26.
  27. // c)
  28. $writer = new Zend_Config_Writer_Xml();
  29. $writer->write('config.xml', $config);

This will create an XML config file with the sections production and staging, where staging extends production.

Example #2 Modifying an Existing Config

This example demonstrates how to edit an existing config file.

  1. // Load all sections from an existing config file, while skipping the extends.
  2. $config = new Zend_Config_Ini('config.ini',
  3.                               null,
  4.                               array('skipExtends'        => true,
  5.                                     'allowModifications' => true));
  6.
  7. // Modify a value
  8. $config->production->hostname = 'foobar';
  9.
  10. // Write the config file
  11. $writer = new Zend_Config_Writer_Ini(array('config'   => $config,
  12.                                            'filename' => 'config.ini'));
  13. $writer->write();

Note: Loading a Config File
 When loading an existing config file for modifications it is very important to load all sections and to skip the extends, so that no values are merged. This is done by giving the skipExtends as option to the constructor.

For all the File-Based writers (INI, XML and PHP Array) internally the render() is used to build the configuration string. This method can be used from the outside also if you need to access the string-representation of the configuration data.

Zend_Config_Writer
Zend_Config_Writer
Zend Framework手册 中文版
Zend_Console_Getopt
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Config_Writer
  • Zend_Config_Writer


Zend_Console_Getopt - Zend Framework Manual

Zend_Config_Writer
Zend Framework Reference
Zend Framework手册 中文版
Getopt 简介

Zend_Console_Getopt

Table of Contents
  • Getopt 简介
  • 声明 Getopt 规则
  • 读取（Fetching）选项和参数
  • 配置 Zend_Console_Getopt
Zend_Config_Writer
Zend Framework Reference
Zend Framework手册 中文版
Getopt 简介
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


Getopt 简介 - Zend Framework Manual

Zend_Console_Getopt
Zend_Console_Getopt
Zend Framework手册 中文版
声明 Getopt 规则

Getopt 简介

Zend_Console_Getopt 类帮助命令行程序解析它们的选项和参数。

当执行你的程序时，用户可以指定命令行参数。这些参数对程序时有意义的，或改变程序的行为，或选择资源，或详细说明参数。许多选项有传统的意义，例如 "--verbose" 对大多数的程序都是允许输出执行细节。一些选项可能对不同的程序有不同的意义。例如 "-c" 在 grep、 ls 和 tar 里有不同的功能。

下面时一些术语的定义。术语的基本用法变化多样，但本文档使用下面的定义。

  • "argument"：在命令之后的字符串。Arguments 可以时选项或其它不带选项的形式，在命令操作时指出资源。

  • "option"：表示命令应该改变其缺省行为的参数。

  • "flag"：选项的第一部分，确定选项的意图。传统上 flag 前面有一个或两个短横线 ("-" 或 "--")。一个单个的短横引导一个单字符的 flag 或 一组单字符的 flags。双横线引导一个多字符的 flag。长的 flags 不能组合。

  • "parameter"：选项的第二部分，如果它适用于给定的选项，就是随 flag 带的数据值。例如，许多命令接受 "--verbose" 选项，但一般这个选项没有参数（parameter）。但象 "--user" 的选项几乎总是有一个参数（ parameter ）。

    parameter 可以作为在 flag 参数之后的分离的参数，或作为同一参数串的一部分，从 flag 里用等号（"="）分开。后者只被长的 flags 支持。例如，-u username、 --user username 和 --user=username 是被 Zend_Console_Getopt 支持的格式。

  • "cluster"：在一个单字串参数里的多个单字符 flags 组合，由单个短横线引导。例如，"ls -1str" 使用一组四个短 flags 。这个命令和 "ls -1 -s -t -r" 相同。只有单个字符 flags 可以被组成组，对长的 flags 不可以组合。

例如，在 "mysql --user=root mydatabase" 里，"mysql" 是 命令 ，"--user=root" 是 option，"--user" 是 flag，"root" 是 option 的 parameter，根据我们的定义 "mydatabase" 是 argument 而不是 option 。

Zend_Console_Getopt 提供了接口来声明哪个 flags 对你的程序有效，如果使用了无效的flag，则输出错误和用法信息，并报告给你的程序代码。

Note: Getopt 不是应用程序框架
Zend_Console_Getopt 不 不翻译 flags 和 parameters 的意思，这个类也不实现程序流程或调用程序代码。你必需在你自己的程序代码中实现这些动作。你可以使用 Zend_Console_Getopt 来解析命令行和提供面向对象的方法来查询由用户给定的 options ，但使用这些信息去调用程序的部分应当在其它 PHP 类里。

后面的章节描述 Zend_Console_Getopt 的用法。

Zend_Console_Getopt
Zend_Console_Getopt
Zend Framework手册 中文版
声明 Getopt 规则
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Console_Getopt
  • Getopt 简介
  • 声明 Getopt 规则
  • 读取（Fetching）选项和参数
  • 配置 Zend_Console_Getopt


声明 Getopt 规则 - Zend Framework Manual

Getopt 简介
Zend_Console_Getopt
Zend Framework手册 中文版
读取（Fetching）选项和参数

声明 Getopt 规则

Zend_Console_Getopt 类的构造器带有一到三个参数。第一个参数声明哪个选项被应用程序支持。这个类支持交替（alternative）语法形式来声明选项。参见下面的章节关于这些语法形式的格式和用法。

构造器带有的另外两个参数都是可选的。第二个参数可以包含命令行参数，缺省为 $_SERVER['argv'] 。

第三个参数包含一个配置选项来定制 Zend_Console_Getopt 的行为（behavior）。关于可用选项的引用（reference），参见 添加配置

用短语法声明选项

Zend_Console_Getopt 支持紧凑的语法 （类似用于 GNU Getopt的语法，参见 » http://www.gnu.org/software/libc/manual/html_node/Getopt.html ）。这个语法只支持单字符 flag 。在一个单个的字符串中，每个字母对应于被程序支持的 flag。字母后跟着冒号 (":") 表示这个 flag 需要参数。

Example #1 使用短语法

$opts = new Zend_Console_Getopt('abp:');

上面的例子示例使用 Zend_Console_Getopt 来声明选项，这个选项也可以以 "-a"、"-b" 或 "-p"的形式给出。后面的 flag 需要一个参数。

短语法限于单个字符的flag。别名，参数类型和帮助字符串不被短语法支持。

用长语法声明选项

带有更多功能的不同的语法也是可用的。这个语法允许为 flag 指定别名、选项参数的类型和用来描述用法的帮助字符串。在短语法中使用单字符串来声明选项，而在常语法中使用联合数组作为构造器的第一个参数。

联合数组的每个元素的键是一个字符串，这个字符串带有给flag命名的格式，用管道符号("|")来隔离每个别名。在这些别名后面，如果选项需要参数，则用等号("=")和紧跟一个字母来表示参数的 类型 ：

  • "=s" 表示字符串参数

  • "=w" 表示一个字的参数（不包含空白的字符串）

  • "=i" 表示整数参数

如果参数是可选的，使用短横线 ("-")而不使用等号。

在联合数组中的每个元素的值是帮助字符串，用来描述如何使用程序。

Example #2 使用长语法

$opts = new Zend_Console_Getopt(
  array(
    'apple|a'    => 'apple option, with no parameter',
    'banana|b=i' => 'banana option, with required integer parameter',
    'pear|p-s'   => 'pear option, with optional string parameter'
  )
);

在上面的声明例子中，有三个选项："--apple" 和 "-a" 互为别名，不带参数；"--banana" and "-b" 互为别名，带有强制的整形参数；最后，"--pear" and "-p" 互为别名，带有可选的字符串参数。

Getopt 简介
Zend_Console_Getopt
Zend Framework手册 中文版
读取（Fetching）选项和参数
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Console_Getopt
  • Getopt 简介
  • 声明 Getopt 规则
  • 读取（Fetching）选项和参数
  • 配置 Zend_Console_Getopt


读取（Fetching）选项和参数 - Zend Framework Manual

声明 Getopt 规则
Zend_Console_Getopt
Zend Framework手册 中文版
配置 Zend_Console_Getopt

读取（Fetching）选项和参数

在声明 Zend_Console_Getopt 对象认可的选项和从命令行或数组提供参数后，可以查询这个对象来找出哪个选项被用户在程序中给定的命令行调用中被指定。这个类实现魔术方法，所以可以用名字来查询选项。

数据的解析被延迟到第一个依靠 Zend_Console_Getopt 对象查询是否发现一个选项被给出，然后这个对象来执行解析。它允许在解析发生之前使用若干个方法调用来配置选项、参数、帮助内容和配置选项。

操作 Getopt 异常

如果用户在命令行中给出任何无效选项，解析函数抛出一个Zend_Console_Getopt_Exception。你应当在程序代码理捕捉这个异常。可以使用parse()方法强制对象来解析参数。这很有用，因为可以在try 块中调用parse()。如果通过，解析不再抛出异常。异常的抛出有一个定制的方法 getUsageMessage()，它作为字符串返回，这个字符串是所有被声明的选项的用法信息。

Example #1 捕捉 Getopt 异常

try {
    $opts = new Zend_Console_Getopt('abp:');
    $opts->parse();
} catch (Zend_Console_Getopt_Exception $e) {
    echo $e->getUsageMessage();
    exit;
}

解析抛出异常的情况包括：

  • 给出的选项不被认可。

  • 选项需要参数，但没有给出。

  • 选项参数类型错误。例如，当要求整数却给出一个非数字字符串。

通过名字读取 （Fetching）选项

可以使用 getOption() 方法来查询选项的值。如果选项有一个参数，这个方法返回参数的值。如果选项不带参数但用户的确在命令行中指定了，这个方法返回true，否则，返回null。

Example #2 使用 getOption()

$opts = new Zend_Console_Getopt('abp:');
$b = $opts->getOption('b');
$p_parameter = $opts->getOption('p');

另外，可以使用魔术函数 __get() 来获取选项的值，好像它是类成员变量。 __isset() 魔术方法也可以实现。

Example #3 使用 __get() 和 __isset() 魔术方法

$opts = new Zend_Console_Getopt('abp:');
if (isset($opts->b)) {
    echo "I got the b option.\n";
}
$p_parameter = $opts->p; // null if not set

如果选项被带有别名声明，在上面的方法中可以使用任何别名。

报告选项

有若干方法来报告由用户在当前命令行给出的选项的全集。

  • 作为字符串：使用toString()方法。选项被返回为用空格分隔的"flag=value"对的字符串。没有参数的选项值是字面上的"true"。

  • 作为数组：使用toArray()方法。选项被返回在一个简单的整数索引的字符串数组，flag 字符串在参数字符串之后，如果有的话。

  • 作为包含JSON数据的字符串：使用 toJson() 方法。

  • 作为包含 XML 数据的字符串： 使用 toXml() 方法。

在上述所有的方法中，flag 字符串是对应于别名列表中的第一个字符串。例如：如果选项别名被声明如"verbose|v"，那么第一个字符串，"verbose"，被用作选项的规范名称。选项flag的名称不包括任何前面所述的短横线。

读取非选项参数

在选项参数和它们的参数从命令行中解析后，可能还有另外的参数剩余。可以使用getRemainingArgs()方法来查询这些参数。这个方法返回一个不属于任何选项的字符串数组。

Example #4 使用 getRemainingArgs()

$opts = new Zend_Console_Getopt('abp:');
$opts->setArguments(array('-p', 'p_parameter', 'filename'));
$args = $opts->getRemainingArgs(); // returns array('filename')

Zend_Console_Getopt支持 GNU 惯例，在参数中包含双短横线表示选项的结尾。在这个符号后面的任何参数必须当作非选项参数。如果有以一个短横线开头的非选项参数，这很有用。例如："rm -- -filename-with-dash"。

声明 Getopt 规则
Zend_Console_Getopt
Zend Framework手册 中文版
配置 Zend_Console_Getopt
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Console_Getopt
  • Getopt 简介
  • 声明 Getopt 规则
  • 读取（Fetching）选项和参数
  • 配置 Zend_Console_Getopt


配置 Zend_Console_Getopt - Zend Framework Manual

读取（Fetching）选项和参数
Zend_Console_Getopt
Zend Framework手册 中文版
Zend_Controller

配置 Zend_Console_Getopt

添加选项规则

使用addRules()方法，可以添加更多除了在Zend_Console_Getopt构造器中指定的选项规则。addRules() 的参数和给这个类的构造器的第一个参数相同。它可以是符合短语法选项规范的字符串，也可以是符合长选项语法的联合数组。关于选项规范语法的细节参见 声明 Getopt 规则 。

Example #1 使用 addRules()

$opts = new Zend_Console_Getopt('abp:');
$opts->addRules(
  array(
    'verbose|v' => 'Print verbose output'
  )
);

上述例子示例添加带有 "-v" 别名的 "--verbose" 选项给在定义在调用构造器的一组选项。注意你可以在Zend_Console_Getopt的同一实例中混合使用短格式选项和长格式选项。

添加帮助信息

除了当声明选项规则为长（语法）格式时指定帮助字符串（帮助信息），也可以用setHelp()方法来联系帮助字符串和选项规则。setHelp()方法的参数时一个联合数组，它的键是一个flag，值是一个相应的帮助字符串。

Example #2 使用 setHelp()

$opts = new Zend_Console_Getopt('abp:');
$opts->setHelp(
    array(
        'a' => 'apple option, with no parameter',
        'b' => 'banana option, with required integer parameter',
        'p' => 'pear option, with optional string parameter'
    )
);

如果被声明的选项带有别名，可使用任何一个别名来作为联合数组的键。

如果使用短语法声明选项，setHelp()方法是定义帮助信息的唯一办法。

添加选项别名

你可以使用setAliases方法为选项声明别名。参数是一个联合数组，它的键为一个先前声明的字符串，值是一个相应于那个 flag 的新的别名。这些别名和已存在的别名合并。换句话说，早先声明的别名仍然有效。

一个别名只能声明一次。如果企图重新定义一个别名，Zend_Console_Getopt_Exception 将被抛出。

Example #3 使用 setAliases()

$opts = new Zend_Console_Getopt('abp:');
$opts->setAliases(
    array(
        'a' => 'apple',
        'a' => 'apfel',
        'p' => 'pear'
    )
);

在上面的例子中，在声明这些别名后，"-a"、 "--apple" 和 "--apfel" 互为别名。"-p" 和 "--pear" 互为别名。

如果使用短语法声明选项，setAliases()方法是定义帮助信息的唯一办法。

添加参数列表

缺省地，Zend_Console_Getopt 使用 $_SERVER['argv'] 作为用来解析的命令行参数数组。你可以另外指定参数数组作为第二个构造器参数。最后，你可以用 addArguments() 方法追加更多的参数给这些已经使用的参数，或者你可以使用 setArguments() 方法替换当前的参数数组。对于这两种情况，这些方法的参数是简单的字符串数组。前者追加数组到当前参数，后者替换当前参数的数组。

Example #4 使用 addArguments() 和 setArguments()

// 缺省地，构造器使用 $_SERVER['argv']
$opts = new Zend_Console_Getopt('abp:');

// 追加数组给当前参数
$opts->addArguments(array('-a', '-p', 'p_parameter', 'non_option_arg'));

// 替换当前的参数
$opts->setArguments(array('-a', '-p', 'p_parameter', 'non_option_arg'));

添加配置

Zend_Console_Getopt 构造器的第三个参数是个影响返回的对象实例行为的配置选项数组。也可以使用 setOptions() 方法指定配置选项， 或者用 setOption() 方法设置一个独立的选项。

Note: 阐明术语 "option"
Zend_Console_Getopt类的配置使用术语 "option" 来匹配在Zend Framework 其它地方使用的术语。这些和Zend_Console_Getopt 类解析的命令行选项不是一回事。

当前支持的选项在类中有常量定义。它们的常量标识符（在括号中的文字）列表如下：

  • Zend_Console_Getopt::CONFIG_DASHDASH ("dashDash")，如果为 true，允许特殊 flag "--" 表示 flag 的结尾。带有双短横线的符号不被翻译为选项，即使参数以一个短横线开头。这个配置选项缺省为 true。

  • Zend_Console_Getopt::CONFIG_IGNORECASE ("ignoreCase")，如果为 true，如果它们不同，使 flags 互为别名。这样，"-a" 和 "-A" 将被认为是同义 flags。这个配置选项缺省为 false。

  • Zend_Console_Getopt::CONFIG_RULEMODE("ruleMode") 可以有 Zend_Console_Getopt::MODE_ZEND ("zend") 和 Zend_Console_Getopt::MODE_GNU ("gnu") 的值。使用这个选项不是必须的除非你用另外的语法形式扩展这个类。这两个方法在 Zend_Console_Getopt 类中明确地支持。如果指定器是字符串， 这个类就假定为 MODE_GNU ，否则它就假定为 MODE_ZEND 。但如果你扩展这个类并添加更多语法形式， 你需要用这个选项来指定模式。

更多的选项可以将被添加为这个类的增强。

setOption() 方法的两个参数是配置选项名称和选项值。

Example #5 使用 setOption()

$opts = new Zend_Console_Getopt('abp:');
$opts->setOption('ignoreCase', true);

setOptions() 方法的参数是一个联合数组。这个数组的键是配置选项名称，（数组的）值是配置（选项）的值。这也是用于类构造器的数组格式。你指定的配置的值和当前配置合并，不需要列出所有的选项。

Example #6 使用 setOptions()

$opts = new Zend_Console_Getopt('abp:');
$opts->setOptions(
    array(
        'ignoreCase' => true,
        'dashDash'   => false
    )
);
读取（Fetching）选项和参数
Zend_Console_Getopt
Zend Framework手册 中文版
Zend_Controller
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Console_Getopt
  • Getopt 简介
  • 声明 Getopt 规则
  • 读取（Fetching）选项和参数
  • 配置 Zend_Console_Getopt


Zend_Controller - Zend Framework Manual

配置 Zend_Console_Getopt
Zend Framework Reference
Zend Framework手册 中文版
Zend_Controller 快速入门

Zend_Controller

Table of Contents
  • Zend_Controller 快速入门
  • Zend_Controller 基础
  • 前端控制器
  • 请求对象
  • 标准路由器
  • 分发器
  • 动作控制器
  • 动作助手
  • 响应对象
  • 插件
  • 使用传统的模块目录结构
  • MVC 异常
配置 Zend_Console_Getopt
Zend Framework Reference
Zend Framework手册 中文版
Zend_Controller 快速入门
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


Zend_Controller 快速入门 - Zend Framework Manual

Zend_Controller
Zend_Controller
Zend Framework手册 中文版
Zend_Controller 基础

Zend_Controller 快速入门

简介

Zend_Controller是Zend Framework的MVC体系的核心部份。MVC指» Model-View-Controller，是一个用于分离应用逻辑和表现逻辑的设计模式。Zend_Controller_Front实现了» Front Controller设计模式，所有的请求都通过front controller(前端控制器)并分发(dispatch)到不同的控制器来处理，分发的过程基于请求的URL。

Zend_Controller体系具有可扩展性，可以通过继承已有的类或者自己写个新的类来实现各种接口和抽象类，也可以编写插件或者助手类(helper)来增强系统的功能。

入门

如果你想深入了解控制器，请认真看下面几节内容，如果你只是想快速地把系统搭建起来，看这一节。

文件系统的组织结构

首先你要规划好自己的文件结构布局，典型的结构是这样的：

application/
    controllers/
        IndexController.php
    models/
    views/
        scripts/
            index/
                index.phtml
        helpers/
        filters/
html/
    .htaccess
    index.php

设置文件根目录

将你的WEB服务器文件根目录指向上面文件布局中的html目录。

创建URL重写规则

创建html/.htaccess，编辑其内容为：

RewriteEngine on
RewriteRule !\.(js|ico|gif|jpg|png|css)$ index.php

在上例中，所有请求(除了对那几个扩展名的文件的请求)都被转向到index.php。如果你想在访问某些扩展名的文件时不转向到index.php，你可以建立自己的URL重写规则，或者直接把扩展名添加到(|)之中去。

Note: 上面的重写规则只能用于Apache服务器，如果你使用的是其它服务器，请查看 router的文档.

创建你的bootstrap文件

(所谓Bootstrap，就相当于一小段引导程序或者入口程序，在ZF中，通常即指index.php，因为我们所有的请求都是从index.php进入的。--Haohappy注) 在设置好 .htaccess文件之后，建立一个新的文件index.php：

Zend_Controller_Front::run('/path/to/app/controllers');

这是一个入口文件，目的仅在于启动Zend_Controller_Front。Zend_Controller_Front用于分配请求到不同的控制器。

创建默认的控制器（Action Controller）

在讨论控制器之前，你应该先理解Zend Framework是如何处理HTTP请求的。默认情况下，URL的第一个部份会映射到一个控制器，第二个部份则映射到控制器类中的Action（即控制器类内部的一个方法）。例如：URLhttp://framework.zend.com/roadmap/components，其服务器路径为/roadmap/components，则会映射到roadmap控制器和components　Action。如果不存在action，则会调用index这个action。如果控制器不存在，则会自动调用index控制器。(按照Apache的命名惯例，自动映射到DirectoryIndex文件)

接下来，Zend_Controller的dispatcher会根据控制器的名称找到具体的控制器类。通常它会把控制器名称加上Controller。因此，上例中roadmap控制器与类RoadmapController相对应。

类似地，action会映射到控制器类中的一个类方法。默认情下，会被转成小写字母，然后加上Action字符串。因此，上例中components这个action与 componentsAction相对应。最终我们访问URL调用的是RoadmapController->componentsAction()

现在让我们来创建一个默认的控制器和Action方法吧。上面说过，默认的控制器和方法都以“index”命名。打开文件application/controllers/IndexController.php，输入：

/** Zend_Controller_Action */
class IndexController extends Zend_Controller_Action
{
    public function indexAction()
    {
    }
}

默认情况下，ViewRenderer会被启用。这意味着只需要简单地下定义一个action方法，就会自动指定一个对应的View脚本，你可在action中直接把内容输出。默认情况下，我们采用Zend_View作为MVC开发的表现层部份。ViewRenderer根据控制器的名称（例如index）和当前的action的名称（例如index）来决定使用哪个模板文件。默认情况下，模板文件使用.phtml作为扩展名。　也就是说，上例中，我们将使用index/index.phtml模板文件。　另外，ViewRenderer自动假设views目录与控制器目录平级，作为视图层的基础目录，而实际的模板文件则放置在views/scripts/ 子目录下。因为我们的模板文件应该是 application/views/scripts/index/index.phtml。

创建你的视图脚本

之前说过，视图脚本（即模板文件）放在application/views/scripts/目录下，而默认的模板是application/views/scripts/index/index.phtml。我们来创建这个文件，加入一些HTML代码：

<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>My first Zend Framework App</title>
</head>
<body>
    <h1>Hello, World!</h1>
</body>
</html>

创建你自己的错误控制器

默认情况下，“错误处理器”插件 是已经被注册的。这个插件要求存在一个用于处理错误的控制器。它假设存在一个ErrorController，并且其中有一个名为errorAction的Action：

class ErrorController extends Zend_Controller_Action
{
    public function errorAction()
    {
    }
}

使用我们之前讨论的目录布局，这个文件将是application/controllers/ErrorController.php，你也需要为它创建一个模板文件，即application/views/scripts/error/error.phtml。其中的内容如下：

<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>错误</title>
</head>
<body>
    <h1>出错了</h1>
    <p>出现了一个错误，请重试。</p>
</body>
</html>

访问站点！

创建好了你的第一个控制器和模板，你现在可以打开浏览器来访问看看了！　假设example.com是你的站点域名，那么下面的URL都会带你访问你刚才创建的页面：

  • http://example.com/

  • http://example.com/index

  • http://example.com/index/index

恭喜你！　你已经准备好了，可以开始创建更多的控制器和Action！

Zend_Controller
Zend_Controller
Zend Framework手册 中文版
Zend_Controller 基础
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Controller
  • Zend_Controller 快速入门
  • Zend_Controller 基础
  • 前端控制器
  • 请求对象
  • 标准路由器
  • 分发器
  • 动作控制器
  • 动作助手
  • 响应对象
  • 插件
  • 使用传统的模块目录结构
  • MVC 异常


Zend_Controller 基础 - Zend Framework Manual

Zend_Controller 快速入门
Zend_Controller
Zend Framework手册 中文版
前端控制器

Zend_Controller 基础

Zend_Controller系统被设计为轻量、模块化、和可扩展的系统。虽然它提供了足够多的功能结构让你的系统建立在Zend_Controller之上并共享通用的约定和相似的代码设计，但它是一个最低要求的设计，给用户最大的灵活性和自由度。

以下图表描述了工作流，下面的说明中详细介绍了之间的交互

< class="inlinemediaobject">

Zend_Controller工作流用若干组件来实现。虽然不需要完全理解所有组件的基础知识来使用它，但是拥有工作流程的知识很有帮助。

  • Zend_Controller_Front 控制了Zend_Controller系统的整个工作流。它是前端控制器（FrontController）模型的解释。Zend_Controller_Front处理所有由服务器接收的请求并负责把请求派发给动作控制器（ActionControllers）(Zend_Controller_Action)。

  • Zend_Controller_Request_Abstract (often referred to as the Request Object)描述请求环境和提供设置和读取控制器和动作名字以及任何请求参数的方法。另外它跟踪它所包含的动作是否被Zend_Controller_Dispatcher派遣。抽象请求对象的扩展可被用来封装整个请求环境，为了设置控制器和动作的名字，它允许路由器从请求环境中读出信息。

    缺省地，Zend_Controller_Request_Http被用来访问整个HTTP请求环境。

  • Zend_Controller_Router_Interface用来定义路由器。路由是个过程，在这个过程中它通过检查请求环境来决定哪个个控制器和哪个控制器中的动作应该接受请求。控制器、动作和可选的参数就通过Zend_Controller_Dispatcher_Standard处理来设置在请求对象中。路由只发生一次：在最初收到请求并在第一个控制器被派遣之前。

    缺省路由器，Zend_Controller_Router_Rewrite，从Zend_Controller_Request_Http取出URI的终点作为参数并基于在url中的路径信息分解成控制器、动作和参数。作为一个例子，URL http://localhost/foo/bar/key/value将被解析为foo控制器、bar 动作和带有一个值value的参数key。

    Zend_Controller_Router_Rewrite也可以用来匹配任意的路径；参见路由器文档 有更多的信息。

  • Zend_Controller_Dispatcher_Interface被用来定义派遣器。派遣是个过程，在这个过程中它从请求对象中取出控制器和动作并映射它们到控制器文件/类和在控制器中的动作方法。如果控制器和动作不存在，它派遣缺省的控制器和动作。

    实际的派遣过程包括初始化控制器类和在这个类中调用动作方法。不像路由，只发生一次，派遣是循环发生的。如果请求对象的派遣状态在任何点上重置，循环将被重复，调用不论哪个当前在请求对象中的动作。第一次循环随请求对象的派遣状态设置（布尔 true）完成，它将完成处理。

    缺省的派遣器是Zend_Controller_Dispatcher_Standard。它定义控制器为以Controller结尾的 MixedCasedClasses，并且动作为以Action结尾的camelCasedMethods：FooController::barAction()。在这个例子中，控制器是foo，动作是the action as bar。

    Note: 大小写命名协议
    因为人们经常在大小写上犯错误，所以Zend Framework把路径信息标准化为小写。当然，这会影响你来命名控制器和动作或指向它们的链接。
    如果你想使你的控制器类和动作方法名称有多个混合大小写字或驼峰字，你需要在url中使用'-'或'.'来把它们分开（尽管你可以配置使用的字符）。
    作为例子，如果你打算用FooBarController::bazBatAction()，那么在url中链接时要用/foo-bar/baz-bat或/foo.bar/baz.bat。

  • Zend_Controller_Action是基本的动作控制器组件。每个控制器是一个从Zend_Controller_Action class扩展的单个的类并且应该包含一个或更多的动作方法。

  • Zend_Controller_Response_Abstract定义了一个基本的响应类，用来从动作控制器收集和返回响应。头和body的内容它都收集。

    缺省的响应类是Zend_Controller_Response_Http，它适合用于HTTP环境。

Zend_Controller的工作流相当简单。请求被Zend_Controller_Front接收，然后它调用Zend_Controller_Router_Rewrite来决定哪个控制器（和控制器中的动作）被派遣。为了在请求中设置控制器和动作名字Zend_Controller_Router_Rewrite分解URI。Zend_Controller_Front接着进入一个派遣循环。它调用Zend_Controller_Dispatcher_Standard，传递给它请求，派遣在请求（或使用缺省的）中指定的控制器和动作。在控制器完成之后，控制返回到Zend_Controller_Front。如果控制器通过重置请求派遣状态指示其它的控制器应该被派遣，循环将继续并且其它派遣被执行。否则，处理结束。

Zend_Controller 快速入门
Zend_Controller
Zend Framework手册 中文版
前端控制器
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Controller
  • Zend_Controller 快速入门
  • Zend_Controller 基础
  • 前端控制器
  • 请求对象
  • 标准路由器
  • 分发器
  • 动作控制器
  • 动作助手
  • 响应对象
  • 插件
  • 使用传统的模块目录结构
  • MVC 异常


前端控制器 - Zend Framework Manual

Zend_Controller 基础
Zend_Controller
Zend Framework手册 中文版
请求对象

前端控制器

概述

Zend_Controller_Front实现了» 模型-视图-控制器 (MVC)应用程序的» 前端控制器模式。目的在于初始化请求环境，并路由到来的请求，接着分发任何发现的动作；收集所有的响应，在整个过程完成时就其返回。

Zend_Controller_Front也实现了» 单件（Singleton）模式，意味着任何时候，都只可能有一个有效实例。这使得它可以作为注册表，供分发过程中的其他对象引用。

Zend_Controller_Front自己注册了一个插件经纪人（plugin broker），允许插件观测它所触发的各种事件。大多数情况下，这将使得开发人员有机会裁剪站点的分发过程，而无需通过扩展前端控制器增加功能。

前端控制器最至少需要一个或多个包含动作控制器的目录的路径来完成工作。还有大量的方法可供调用，进一步裁剪前端控制器以及它的助手类环境。

Note: 默认的行为
 默认地，前端控制器加载ErrorHandler插件，以及ViewRenderer动作助手，分别为了简化控制器中的错误处理和视图渲染。
如需禁用ErrorHandler，调用dispatch()前执行下面代码：

// Disable the ErrorHandler plugin:
$front->setParam('noErrorHandler', true);
如需禁用ViewRenderer，调用dispatch()前执行下面代码：
// Disable the ViewRenderer helper:
$front->setParam('noViewRenderer', true);

主要方法

前端控制器有很多建立其环境的访问器。但是，有三个是开启前端控制器功能的主要方法：

getInstance()

getInstance()方法用来获取前端控制器实例。因为前端控制器实现了单件模式，这可能是唯一创建前端控制器对象的方法。

$front = Zend_Controller_Front::getInstance();

setControllerDirectory() 和 addControllerDirectory()

setControllerDirectory()通知分发器到哪查找动作控制器action controller类文件。参数接受单一路径和模块/路径对关联数组。

例如：

// Set the default controller directory:
$front->setControllerDirectory('../application/controllers');

// Set several module directories at once:
$front->setControllerDirectory(array(
    'default' => '../application/controllers',
    'blog'    => '../modules/blog/controllers',
    'news'    => '../modules/news/controllers',
));

// Add a 'foo' module directory:
$front->addControllerDirectory('../modules/foo/controllers', 'foo');

Note: 如果使用addControllerDirectory()时不带模块名，将会为default模块设定目录——如果目录已设定，就覆盖掉。

可以通过getControllerDirectory()获取控制器目录的当前设置；它将返回一个模块/目录对关联数组。

addModuleDirectory() and getModuleDirectory()

前端控制器的一个功能是你可以 定义一个模块目录结构 来创建独立的组件，被叫做“模块”。

每个模块位于自己的目录并和缺省模块的目录结构一样 － 例如，它至少 有个 "controllers" 字目录和 "views" 子目录以及其它应用子目录。

addModuleDirectory() 让你传递一个包含一个或多个模块目录的目录名。 然后进行扫描并把它们作为控制器目录添加到前端控制器。

然后，如果你想确定特定模块或当前模块路径，调用 getModuleDirectory()， 可选地传递模块名来获得模块目录。

dispatch()

dispatch(Zend_Controller_Request_Abstract $request = null, Zend_Controller_Response_Abstract $response = null)完成前端控制器最繁重的工作。该方法带有可选的参数请求对象和/或响应对象，允许开发人员为每一个传入定制的对象。

如果没有请求或者响应对象传入，dispatch()将检查先前注册的对象并使用，如果没有发现则创建默认的对象版本（它们两个都默认使用HTTP对象）。

类似的，dispatch()先检查已注册的路由器（router）和分发器（dispatcher）对象，如果没有发现则实例化它们的默认版本。

分发过程有三个不同的事件：

  • 路由（Routing）

  • 分发（Dispatching）

  • 响应（Response）

路由只发生一次，当调用dispatch()时利用请求对象中的值。分发发生在一个循环中;请求可能指示 分发多个动作，或者控制器或插件可能重置请求对象，强制分发附加的动作。所有都完成后，前端控制器返回响应对象。

run()

Zend_Controller_Front::run($path)是静态方法，只带一个参数，就是指向包含控制器的目录的路径。它首先通过getInstance()获取前端控制器实例，然后通过setControllerDirectory()注册传入的路径，最后分发。

基本上，如果不要求定制前端控制器环境，run()是一个很方便的建立前端控制器环境的方法。

// Instantiate front controller, set controller directory, and dispatch in one
// easy step:
Zend_Controller_Front::run('../application/controllers');

环境访问器方法

除了上面所列的方法以外，还有很多访问器方法可以影响前端控制器环境 —— 因而也影响前端控制器代理（delegate）的类的环境。

  • resetInstance()方法清除当前的所有设置。主要用来测试，不过，在希望将几个前端控制器连锁的地方也是很有用的（but it can also be used for instances where you wish to chain together multiple front controllers）。

  • (set|get)DefaultControllerName()方法可以为默认的控制器指定另外一个名字（否则使用'index'），以及获取当前值。它们将代理分发器。

  • (set|get)DefaultAction()方法可以为默认的动作指定另外一个名字（否则使用'index'）,以及获取当前值。它们将代理分发器。

  • (set|get)Request()方法指定分发过程中使用的请求类或对象，以及获取当前的请求对象。设置请求对象时，可以传入一个请求类的名字，该方法将加载类文件并创建实例。

  • (set|get)Router()方法指定分发过程中使用的路由器类或对象，以及获取当前对象。设置路由器时，可以传入一个路由器类的名字，该方法将加载类文件并创建实例。

    获取路由器对象的时候，首先检查是否已有一个，如果没有，创建默认的路由器实例（rewrite路由器）。

  • (set|get)BaseUrl()方法指定路由请求时剥离（strip）的基地址（base URL），以及获取当前值。这个值将在路由前提供给路由器。

  • (set|get)Dispatcher()方法指定分发过程中使用的分发器类或对象，以及获取当前对象。设定分发器对象时，可以传入一个分发器类的名字，该方法将加载类文件并创建实例。

    获取分发器对象时，首先检查是否已有一个存在，如果没有，将创建一个默认的分发器实例。

  • (set|get)Response()方法指定分发过程中使用的响应类或对象，已经获取当前对象。设定响应对象时，可以传入一个响应类的名字，该方法将加载类文件并创建实例。

  • registerPlugin(Zend_Controller_Plugin_Abstract $plugin, $stackIndex = null)方法允许注册一个插件对象。通过设置可选参数$stackIndex，插件执行的顺序。

  • unregisterPlugin($plugin)方法移除插件对象。$plugin可以是一个插件对象或者代表移除插件类的字符串。

  • throwExceptions($flag)方法用来开启或者关闭分发过程中抛出异常的能力。默认的，异常引起并放置在响应对象中；开启throwExceptions()将覆盖这一行为。

    想知道更多信息的话，请阅读MVC 异常。

  • returnResponse($flag)方法通知前端控制器是否从dispatch()中返回请求对象（true），否则自动发送响应对象（false—）。默认的，响应对象被自动发送（通过调用Zend_Controller_Response_Abstract::sendResponse()）；开启returnResponse()将覆盖这一行为。

    返回响应对象的原因包括希望在发送响应前检查异常，记录响应的各种属性（例如消息头）等等。

前端控制器参数

介绍里曾提到前端控制器可以用作各种控制器组件的注册表。它通过一个"param"家族的方法来做到这些。这些方法允许通过前端控制器注册任意类型的数据 —— 对象和变量，可以在分发链中的任何时候获取。这些变量被传递到路由器，分发器，以及动作控制器。这些方法包括：

  • setParam($name, $value)方法设定值为$value的单个参数$name。

  • setParams(array $params)方法通过关联数组一次设定多个参数。

  • getParam($name)方法通过$name标识符获取单个参数。

  • getParams()方法一次获取整个参数列表。

  • clearParams()方法可以清空一个参数（传入单个字符串标识符），清空多个参数（传入字符串标识符数组），清空整个参数栈（不传入参数）。

有几个预定义的参数可供设定，它们在分发链中有特别的用途：

  • useDefaultControllerAlways用来提示 分发器遇到无法分发的请求时使用默认模块的默认控制器。这默认是关闭的。

    阅读可能遭遇的MVC异常获得使用该设定的更详尽信息。

  • disableOutputBuffering用来提示 is used to hint to 分发器不使用输出缓冲来捕捉动作控制器产生的输出。默认的，分发器捕捉任何输出并追加到响应对象的主体内容。

  • noViewRenderer用来禁用ViewRenderer。设定该参数为true可以禁用该助手。

  • noErrorHandler 用来禁用错误处理器插件。设定该参数为true可以禁用该插件。

继承前端控制器

要继承前端控制器，至少需要覆盖getInstance()方法：

class My_Controller_Front extends Zend_Controller_Front
{
    public static function getInstance()
    {
        if (null === self::$_instance) {
            self::$_instance = new self();
        }

        return self::$_instance;
    }
}

覆盖getInstance()保证后面调用Zend_Controller_Front::getInstance()会返回子类的实例，而不是Zend_Controller_Front实例 —— 这对于一些可替换的路由器和视图助手非常有用。

通常不需要继承前端控制器，除非你需要增加新的功能（比如，一个插件自动加载器，或者一个方法来指定动作助手路径）。你想要改动的地方可能包括修改控制器目录的存储方式，使用的默认路由器以及分发器。

Zend_Controller 基础
Zend_Controller
Zend Framework手册 中文版
请求对象
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Controller
  • Zend_Controller 快速入门
  • Zend_Controller 基础
  • 前端控制器
  • 请求对象
  • 标准路由器
  • 分发器
  • 动作控制器
  • 动作助手
  • 响应对象
  • 插件
  • 使用传统的模块目录结构
  • MVC 异常


请求对象 - Zend Framework Manual

前端控制器
Zend_Controller
Zend Framework手册 中文版
标准路由器

请求对象

介绍

请求对象是在前端控制器，路由器，分发器，以及控制类间传递的简单值对象。请求对象封装了请求的模块，控制器，动作以及可选的参数，还包括其他的请求环境，如HTTP，CLI，PHP-GTK。

  • 模块名可通过getModuleName()和setModuleName()访问。

  • 控制器名可通过getControllerName()和setControllerName()访问。

  • 控制器调用的动作名称可通过getActionName()和setActionName()访问。

  • 可访问的参数是一个键值对的关联数组。数组可通过getParams()和 setParams()获取及设置，单个参数可以通过 getParam() 和 setParam()获取及设置。

基于请求的类型存在更多的可用方法。默认的Zend_Controller_Request_Http请求对象，拥有访问请求url、路径信息、$_GET 和 $_POST参数的方法等等。

请求对象先被传入到前端控制器。如果没有提供请求对象，它将在分发过程的开始、任何路由过程发生之前实例化。请求对象将被传递到分发链中的每个对象。

而且，请求对象在测试中是很有用的。开发人员可根据需要搭建请求环境，包括模块、控制器、动作、参数、URI等等，并且将其传入前端控制器来测试程序流向。如果与响应对象配合，可以对MVC程序进行精确巧妙的单元测试(unit testing)。

HTTP 请求

访问请求数据

Zend_Controller_Request_Http封装了对相关值的访问，如控制器和动作路由器变量的键名和值，从URL解析的附加参数。它还允许访问作为公共成员的超全局变量，管理当前的基地址(Base URL)和请求URI。超全局变量不能在请求对象中赋值，但可以通过setParam/getParam方法设定/获取用户参数。

Note: 超全局数据
 通过Zend_Controller_Request_Http访问公共成员属性的超全局数据,有必要认识到一点，这些属性名(超全局数组的键)按照特定次序匹配超全局变量：1. GET，2.POST，3. COOKIE，4. SERVER，5. ENV。

特定的超全局变量也可以选择特定的方法来访问，如$_POST['user']可以调用请求对象的getPost('user')访问，getQuery()可以获取$_GET元素，getHeader()可以获取请求消息头。

Note: GET和POST数据
 需要注意：在请求对象中访问数据是没有经过任何过滤的，路由器和分发器根据任务来验证过滤数据，但在请求对象中没有任何处理。

Note: 也获取原始 （Raw） POST 数据！
 从 1.5.0 开始，也可以通过 getRawBody() 方法获取原始 post 数据。如果没有数据以那种方式提交，该方法返回 false，但 post 的全体（full boday）是个例外。
当开发一个 RESTful MVC 程序，这个对于接受内容相当有用。

可以在请求对象中使用setParam() 和getParam()来设置和获取用户参数。 路由器根据请求URI中的参数，利用这项功能请求对象设定参数。

Note: getParam()不只可以获取用户参数
 getParam()事实上从几个资源中获取参数。根据优先级排序：通过setParam()设置的用户参数，GET 参数，最后是POST参数。 通过该方法获取数据时需要注意这点。

如果你希望从你通过 setParam() 设置的参数中获取（参数），使用 getUserParam()。

另外，从 1.5.0 开始，可以锁定搜索哪个参数源，setParamSources() 允许指定一个空数组或者一个带有一个或多个指示哪个参数源被允许（缺省两者都被允许）的值 '_GET'或'_POST'的数组；如果想限制只访问 '_GET'，那么指定 setParamSources(array('_GET')) 。

Note: Apache相关
 如果使用apache的404处理器来传递请求到前端控制器，或者使用重写规则(rewrite rules)的PT标志，URI包含在$_SERVER['REDIRECT_URL']，而不是$_SERVER['REQUEST_URI']。如果使用这样的设定并获取无效的路由，应该使用Zend_Controller_Request_Apache404类代替默认的HTTP类：

$request = new Zend_Controller_Request_Apache404();
$front->setRequest($request);
这个类继承了Zend_Controller_Request_Http，并简单的修改了请求URI的自动发现(autodiscovery)，它可以用来作为简易替换器件(drop-in replacement)。

基地址和子目录

Zend_Controller_Request_Http允许在子目录中使用Zend_Controller_Router_Rewrite。Zend_Controller_Request_Http试图自动的检测你的基地址，并进行相应的设置。

例如，如果将 index.php 放在web服务器的名为/projects/myapp/index.php子目录中，基地址应该被设置为/projects/myapp。计算任何路由匹配之前将先从路径中去除这个字符串。这个字串需要被加入到任何路由前面。路由 'user/:username'将匹配类似http://localhost/projects/myapp/user/martel 和http://example.com/user/martel的URL。

Note: URL检测区分大小写
 基地址的自动检测是区分大小写的，因此需要确保URL与文件系统中的子目录匹配。否则将会引发异常。

如果基地址经检测不正确，可以利用Zend_Controller_Request_Http或者Zend_Controller_Front类的setBaseUrl()方法设置自己的基路径。Zend_Controller_Front设置最容易，它将导入基地址到请求对象。定制基地址的用法举例：

/**
 * Dispatch Request with custom base URL with Zend_Controller_Front.
 */
$router     = new Zend_Controller_Router_Rewrite();
$controller = Zend_Controller_Front::getInstance();
$controller->setControllerDirectory('./application/controllers')
           ->setRouter($router)
           ->setBaseUrl('/projects/myapp'); // set the base url!
$response   = $controller->dispatch();

决定请求方式

getMethod() 允许你决定用于请求当前资源的 HTTP 请求方法。另外，当询问是否一个请求的特定类型是否已经存在，有许多方法允许你获得布尔响应：

  • isGet()

  • isPost()

  • isPut()

  • isDelete()

  • isHead()

  • isOptions()

这些基本用例是来创建 RESTful MVC 架构的。

删除 AJAX 请求

Zend_Controller_Request_Http 有一个初步的方法用来检测AJAX请求：isXmlHttpRequest()。这个方法寻找一个带有'XMLHttpRequest' 值的HTTP请求头X-Requested-With；如果发现，就返回true。

当前，这个头用下列JS库缺省地传递：

  • Prototype/Scriptaculous (and libraries derived from Prototype)

  • Yahoo! UI Library

  • jQuery

  • MochiKit

大多数 AJAX 库允许发送定制的HTTP请求头；如果你的库没有发送这个头，简单地把它作为一个请求头添加上确保isXmlHttpRequest() 方法工作。

子类化请求对象

所有请求对象的基请求类是抽象类Zend_Controller_Request_Abstract。定义了一些最基本的方法：

abstract class Zend_Controller_Request_Abstract
{
    /**
     * @return string
     */
    public function getControllerName();

    /**
     * @param string $value
     * @return self
     */
    public function setControllerName($value);

    /**
     * @return string
     */
    public function getActionName();

    /**
     * @param string $value
     * @return self
     */
    public function setActionName($value);

    /**
     * @return string
     */
    public function getControllerKey();

    /**
     * @param string $key
     * @return self
     */
    public function setControllerKey($key);

    /**
     * @return string
     */
    public function getActionKey();

    /**
     * @param string $key
     * @return self
     */
    public function setActionKey($key);

    /**
     * @param string $key
     * @return mixed
     */
    public function getParam($key);

    /**
     * @param string $key
     * @param mixed $value
     * @return self
     */
    public function setParam($key, $value);

    /**
     * @return array
     */
     public function getParams();

    /**
     * @param array $array
     * @return self
     */
    public function setParams(array $array);

    /**
     * @param boolean $flag
     * @return self
     */
    public function setDispatched($flag = true);

    /**
     * @return boolean
     */
    public function isDispatched();
}

请求对象是请求环境的容器。控制器链实际上只需要知道如何设置和获取控制器、动作，可选的参数以及分发的状态。默认的，请求将使用controller和action键查询自己的参数来确定控制器和动作。

需要一个请求类来与特定的环境交互以获得需要的数据时，可以扩展该基类或它的衍生类。例如HTTP环境，CLI环境，或者PHP-GTK环境。

前端控制器
Zend_Controller
Zend Framework手册 中文版
标准路由器
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Controller
  • Zend_Controller 快速入门
  • Zend_Controller 基础
  • 前端控制器
  • 请求对象
  • 标准路由器
  • 分发器
  • 动作控制器
  • 动作助手
  • 响应对象
  • 插件
  • 使用传统的模块目录结构
  • MVC 异常


标准路由器 - Zend Framework Manual

请求对象
Zend_Controller
Zend Framework手册 中文版
分发器

标准路由器

简介

Zend_Controller_Router_Rewrite是标准的框架路由器。路由是个过程，在这个过程中它取出URI的端点（跟着基本URL的URI的那部分）并把它分解成参数来决定哪个模块、哪个控制器和控制器中的哪个动作应该接受请求。模块、控制器、动作和其它参数被打包到Zend_Controller_Request_Http对象，接着这个对象由Zend_Controller_Dispatcher_Standard来处理。路由只发生一次：当请求最初被接收和第一个控制器被派遣之前。

Zend_Controller_Router_Rewrite被设计来考虑使用纯php结构时mod_rewrite-like的功能性。它非常宽松地基于Ruby on Rails并且不要求任何先前的web服务器URL rewriting的知识。它被设计来和单个Apache的 mod_rewrite规则（其中之一）一起工作：

RewriteEngine on
RewriteRule !\.(js|ico|gif|jpg|png|css)$ index.php

或者：

RewriteEngine on
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1

如果» Isapi_Rewrite已经用下列的rewrite规则被安装为一个Isapi扩展， rewrite路由器也可以和IIS web服务器一起使用：

RewriteRule ^[\w/\%]*(?:\.(?!(?:js|ico|gif|jpg|png|css)$)[\w\%]*$)? /index.php [I]

Note: IIS Isapi_Rewrite
 当使用IIS，$_SERVER['REQUEST_URI']将要么不存在，要么被设置成一个空串。在这个例子中，Zend_Controller_Request_Http将企图使用被Isapi_Rewrite扩展设置的$_SERVER['HTTP_X_REWRITE_URL']的值。

如果使用 Lighttpd，下面的 rewrite 规则有效：

url.rewrite-once = (
    ".*\?(.*)$" => "/index.php?$1",
    ".*\.(js|ico|gif|jpg|png|css)$" => "$0",
    "" => "/index.php"
)

使用路由器

为正确使用rewrite路由器你必须初始化它，添加一些用户定义的路由并注入到控制器。下面的代码示例这个过程：

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

基本的Rewrite路由器操作

RewriteRouter的核心是用户定义路由的定义。路由通过调用RewriteRouter的addRoute方法和传递一个由类实现的Zend_Controller_Router_Route_Interface的新的实例被添加。例如：

$router->addRoute('user',
                  new Zend_Controller_Router_Route('user/:username'));

Rewrite 路由器带有四个基本类型的路由（其中一个是特殊的）：

  • Zend_Controller_Router_Route

  • Zend_Controller_Router_Route_Static

  • Zend_Controller_Router_Route_Regex

  • 缺省路由 *

路由可以被使用无数次来创建链或用户定义的应用程序路由计划。你可以在任何配置中使用任何数量的路由，除了模块路由以外，它最好被用一次并作为通用路由（例如，作为缺省的）。每个路由将在稍后详细描述。

addRoute的第一个参数是路由名。它用来作为权柄从路由器中取得路由（例如，for URL generation purposes）。第二个参数是路由自己。

Note: 路由名最普通的用法是通过Zend_View_url助手的方法：

"<?= $this->url(array('username' => 'martel'), 'user') ?>">Martel</a>
它将导致在 href： user/martel.

路由是一个简单的过程，这个过程通过所有提供的路由和匹配它的当前请求的URI定义来迭代。当一个正匹配被发现，变量值从路由实例返回并注入到Zend_Controller_Request对象以备将来在派遣器和用户创建的控制器中使用。如果是负匹配，在链中的下个路由被检查。

Note: 倒序匹配
 用倒序来匹配路由确保最通用的路由被首先定义。

Note: 返回的值
 从路由返回的值来自于URL参数或用于定义的缺省值。这些变量以后可通过Zend_Controller_Request::getParam() 或 Zend_Controller_Action::_getParam() 方法来访问。

有三个特殊的变量可用于你的路由－'module'、 'controller' 和 'action'。这些特殊的变量被Zend_Controller_Dispatcher用来找出控制器和动作然后派遣过去。

Note: 特殊变量
 如果你选择通过 setControllerKey 和 setActionKey方法的方式来改变缺省值，这些特殊变量的名字可能会不同。

缺省路由

Zend_Controller_Router_Rewrite 和缺省路由一起预先配置，它将以controller/action的形式匹配URIs。另外，模块名可以被指定作为第一个路径参数，允许这种module/controller/action形式的URIs。最后，它也将缺省地匹配任何另外的追加到URI的参数－controller/action/var1/value1/var2/value2。

一些路由如何匹配的例子：

// Assuming the following:
$ctrl->setControllerDirectory(
    array(
        'default' => '/path/to/default/controllers',
        'news'    => '/path/to/news/controllers',
        'blog'    => '/path/to/blog/controllers'
    )
);

Module only:
http://example/news
    module == news

Invalid module maps to controller name:
http://example/foo
    controller == foo

Module + controller:
http://example/blog/archive
    module     == blog
    controller == archive

Module + controller + action:
http://example/blog/archive/list
    module     == blog
    controller == archive
    action     == list

Module + controller + action + params:
http://example/blog/archive/list/sort/alpha/date/desc
    module     == blog
    controller == archive
    action     == list
    sort       == alpha
    date       == desc

缺省路由是存储在RewriteRouter名（index）为'default'的简单的Zend_Controller_Router_Route_Module对象。它被创建多多少少象下面这样：

$compat = new Zend_Controller_Router_Route_Module(array(),
                                                  $dispatcher,
                                                  $request);
$this->addRoute('default', $compat);

如果你不想这个特别的缺省路由在你的路由计划中，你可以重写你自己的‘缺省’路由（例如，把它存储在'default'名下）或用removeDefaultRoutes()完全清除它：

// Remove any default routes
$router->removeDefaultRoutes();

基本 URL 和子目录

rewrite路由器可以被用在子目录（例如，http://domain.com/~user/application-root/），在此例中，应用程序 (/~user/application-root)的基本URL应该能自动被Zend_Controller_Request_Http检测到并使用。

如果基本URL被误删除，你可以通过Zend_Controller_Request_Http 和调用 setBaseUrl() 方法（参见基地址和子目录）用你自己的基本路径重写它。

$request->setBaseUrl('/~user/application-root/');

Route Types

Zend_Controller_Router_Route

Zend_Controller_Router_Route 是标准的框架路由。它结合了灵活路由定义的易用性。每个路由包含了基本的URL映射（静态的和动态的部分（变量））并且可以被缺省地初始化，也可以根据不同的要求初始化。

让我们想象一下我们假设的应用程序将需要一些广域内容作者的信息页面。我们想能够把浏览器指向http://domain.com/author/martel去看一个叫"martel"的信息。有这样功能的路由看起来是这样的：

$route = new Zend_Controller_Router_Route(
    'author/:username',
    array(
        'controller' => 'profile',
        'action'     => 'userinfo'
    )
);

$router->addRoute('user', $route);

在Zend_Controller_Router_Route里构造函数的第一个参数是路由的定义，它将匹配一个URL。路由定义包含静态的和动态部分，它们由正斜杠('/')符分开。静态部分只是简单的字符：author。动态部分，被叫做变量，用预设的冒号来标记变量名：:username。

Note: 字符的的用法
 当前的实现允许你使用任何字符（正斜杠除外）作为变量标识符，但强烈建议只使用PHP使用的变量标识符。将来的实现也许会改变这个行为，它可能会导致在你的代码里有隐藏的bugs。

当你把浏览器指向http://domain.com/author/martel这个例子的路由应该被匹配，它所有的变量将被注入到Zend_Controller_Request对象并在ProfileController可访问。由这个例子返回的变量可能会被表示为如下键和值配对的数组：

$values = array(
    'username'   => 'martel',
    'controller' => 'profile',
    'action'     => 'userinfo'
);

稍后，基于这些值，Zend_Controller_Dispatcher_Standard应该调用ProfileController类（在缺省模块中）中的userinfoAction()方法。你将依靠Zend_Controller_Action::_getParam()或者Zend_Controller_Request::getParam()方法能够访问所有的变量：

public function userinfoAction()
{
    $request = $this->getRequest();
    $username = $request->getParam('username');

    $username = $this->_getParam('username');
}

路由定义可以包一个额外的特别字符－通配符－表示为'*'号。它被用来取得参数，和缺省模块路由类似（在URI中定义的var=>value）。下面的路由多多少少地模仿了模块路由的行为：

$route = new Zend_Controller_Router_Route(
    ':module/:controller/:action/*',
    array('module' => 'default')
);
$router->addRoute('default', $route);

变量缺省

在路由中每个变量可以有一个缺省值，这就是Zend_Controller_Router_Route中构造函数使用的第二个变量。这个参数是一个数组，在数组中键表示变量名，值就是期望的缺省值：

$route = new Zend_Controller_Router_Route(
    'archive/:year',
    array('year' => 2006)
);
$router->addRoute('archive', $route);

上述路由将匹配象http://domain.com/archive/2005和http://example.com/archive的URLs。对于后者变量year将有一个初始的缺省值为2006。

这个例子将导致注入一个year变量给请求对象。应为没有路由信息出现（没有控制器和动作参数被定义），应用程序将被派遣给缺省的控制器和动作方法（它们都在Zend_Controller_Dispatcher_Abstract被定义）。为使它更可用，你必须提供一个有效的控制器和动作作为路由的缺省值：

$route = new Zend_Controller_Router_Route(
    'archive/:year',
    array(
        'year'       => 2006,
        'controller' => 'archive',
        'action'     => 'show'
    )
);
$router->addRoute('archive', $route);

这个路由将导致派遣给ArchiveController类的showAction()方法。

变量请求

当变量请求被设定，第三个参数可以加给Zend_Controller_Router_Route的构造函数。这些被定义为正则表达式的一部分：

$route = new Zend_Controller_Router_Route(
    'archive/:year',
    array(
        'year'       => 2006,
        'controller' => 'archive',
        'action'     => 'show'
    ),
    array('year' => '\d+')
);
$router->addRoute('archive', $route);

用上述定义的路由，路由器仅当year变量包含数字数据将匹配它，例如http://domain.com/archive/2345。象http://example.com/archive/test这样的URL将不被匹配并且控制将被传递给在链中的下一个路由。

主机名路由

你也可以使用主机名做路由匹配。对简单的匹配使用静态主机名选项：

$route = new Zend_Controller_Router_Route(
    array(
        'host' => 'blog.mysite.com',
        'path' => 'archive'
    ),
    array(
        'module'     => 'blog',
        'controller' => 'archive',
        'action'     => 'index'
    )
);
$router->addRoute('archive', $route);

如果你想匹配参数在主机名里，使用 regex 选项。在下面例子中，子域为动作控制器被用作用户名参数。 当组装路由时，你可以给出用户名为参数，就像你用其它路径参数一样：

$route = new Zend_Controller_Router_Route(
    array(
        'host' => array(
            'regex'   => '([a-z]+).mysite.com',
            'reverse' => '%s.mysite.com'
            'params'  => array(
                1 => 'username'
            )
        ),
        'path' => ''
    ),
    array(
        'module'     => 'users',
        'controller' => 'profile',
        'action'     => 'index'
    )
);
$router->addRoute('profile', $route);

Zend_Controller_Router_Route_Static

上面的例子都使用动态路由－－包含模型来匹配的路由。然而有时候，特定的路由被设定成型，启动正则表达式引擎将有过渡的杀伤力。对这种情形的答案是使用静态路由：

$route = new Zend_Controller_Router_Route_Static(
    'login',
    array('controller' => 'auth', 'action' => 'login')
);
$router->addRoute('login', $route);

上面的路由将匹配http://domain.com/login的URL，并分派到 AuthController::loginAction().

Zend_Controller_Router_Route_Regex

除了缺省的和静态的路由类型外，正则表达式路由类型也可用。这个路由比其它路由更强更灵活，只是稍微有点复杂。同时，它应该比标准路由快。

象标准路由一样，这个路由必须用路由定义和一些缺省条件来初始化。让我们创建一个archive路由作为例子，和先前定义的类似，这次只是用了Regex：

$route = new Zend_Controller_Router_Route_Regex(
    'archive/(\d+)',
    array(
        'controller' => 'archive',
        'action'     => 'show'
    )
);
$router->addRoute('archive', $route);

每个定义的regex子模式将被注入到请求对象里。同上述的例子，再成功匹配http://domain.com/archive/2006之后，结果值的数组看起来象这样：

$values = array(
    1            => '2006',
    'controller' => 'archive',
    'action'     => 'show'
);

Note: 在匹配之前，开头和结尾的斜杠从路由器里的URL中去除掉了。结果，匹配http://domain.com/foo/bar/，需要foo/bar这样的regex，而不是/foo/bar。

Note: 行开头和行结尾符号（分别为'^' 和 '$'）被自动预先追加到所有表达式。这样，你不需要在你的正则表达式里用它们，你应该匹配整个字符串。

Note: 这个路由类使用#符作为分隔符。这意味着你将需要避免哈希符（'#'）但不是正斜杠（'/'）在你的路由定义里。因为'#'符（名称为锚）很少被传给webserver，你将几乎不需要在你的regex里使用它。

你可以用通常的办法获得已定义的子模式的内容：

public function showAction()
{
    $request = $this->getRequest();
    $year    = $request->getParam(1); // $year = '2006';
}

Note: 注意这个键是整数(1) 而不是字符串('1')。

因为'year'的缺省没有设置，这个路由将和它的标准路由副本不是非常精确地相同。即使我们为'year'声明一个缺省并使子模式可选，也不清楚是否会在拖尾斜杠(trailing slash)上还将有问题。方案是使整个'year'部分和斜杠一起可选但只抓取数字部分：（这段比较绕口，请校对者仔细看看，谢谢 Jason Qi）

$route = new Zend_Controller_Router_Route_Regex(
    'archive(?:/(\d+))?',
    array(
        1            => '2006',
        'controller' => 'archive',
        'action'     => 'show'
    )
);
$router->addRoute('archive', $route);

让我们看看你可能注意到的问题。 给参数使用基于整数的键不是容易管理的办法，今后可能会有问题。这就是为什么有第三个参数。这是个联合数组表示一个regex子模式到参数名键的映射。我们来看看一个简单的例子：

$route = new Zend_Controller_Router_Route_Regex(
    'archive/(\d+)',
    array(
        'controller' => 'archive',
        'action' => 'show'
    ),
    array(
        1 => 'year'
    )
);
$router->addRoute('archive', $route);

这将导致下面的值被注入到请求：

$values = array(
    'year'       => '2006',
    'controller' => 'archive',
    'action'     => 'show'
);

这个映射被任何目录来定义使它能工作于任何环境。键可以包含变量名或子模式索引：

$route = new Zend_Controller_Router_Route_Regex(
    'archive/(\d+)',
    array( ... ),
    array(1 => 'year')
);

// OR

$route = new Zend_Controller_Router_Route_Regex(
    'archive/(\d+)',
    array( ... ),
    array('year' => 1)
);

Note: 子模式键必须用整数表示。

注意在请求值中的数字索引不见了，代替的是一个名字变量。当然如果你愿意可以把数字和名字变量混合使用：

$route = new Zend_Controller_Router_Route_Regex(
    'archive/(\d+)/page/(\d+)',
    array( ... ),
    array('year' => 1)
);

这将导致在请求中有混合的值可用。例如：URLhttp://domain.com/archive/2006/page/10将在下列结果中：

$values = array(
    'year'       => '2006',
    2            => 10,
    'controller' => 'archive',
    'action'     => 'show'
);

因为regex模型不容易颠倒，如果你想用URL助手或这个类中的 assemble方法，你需要准备一个颠倒的URL。这个颠倒的路径用可由sprintf()解析的字符串来表示并定义为第四个构造参数：

$route = new Zend_Controller_Router_Route_Regex(
    'archive/(\d+)',
    array( ... ),
    array('year' => 1),
    'archive/%s'
);

所有这些都已经可能由标准路由对象完成，那么使用Regex路由的好处在哪里？首先，它允许你不受限制地描述任何类型的URL。想象一下你有一个博客并希望创建象http://domain.com/blog/archive/01-Using_the_Regex_Router.html这样的URLs，还有把解析它路径元素中的最后部分，01-Using_the_Regex_Router.html，到一个文章的ID和文章的标题/描述；这不可能由标准路由完成。用Regex路由，你可以做象下面的方案：

$route = new Zend_Controller_Router_Route_Regex(
    'blog/archive/(\d+)-(.+)\.html',
    array(
        'controller' => 'blog',
        'action'     => 'view'
    ),
    array(
        1 => 'id',
        2 => 'description'
    ),
    'blog/archive/%d-%s.html'
);
$router->addRoute('blogArchive', $route);

正如你所看到的，这个在标准路由上添加了巨大的灵活性。

使用 Zend_Config with the RewriteRouter

有时候，用新路由更新配置文件比修改代码更方便。这个可能通过addConfig()方法来做。基本上，你创建一个Zend_Config-compatible配置，并在你的代码中读入然后传递给RewriteRouter。

作为例子，考虑下面的 INI 文件：

[production]
routes.archive.route = "archive/:year/*"
routes.archive.defaults.controller = archive
routes.archive.defaults.action = show
routes.archive.defaults.year = 2000
routes.archive.reqs.year = "\d+"

routes.news.type = "Zend_Controller_Router_Route_Static"
routes.news.route = "news"
routes.news.defaults.controller = "news"
routes.news.defaults.action = "list"

routes.archive.type = "Zend_Controller_Router_Route_Regex"
routes.archive.route = "archive/(\d+)"
routes.archive.defaults.controller = "archive"
routes.archive.defaults.action = "show"
routes.archive.map.1 = "year"
; OR: routes.archive.map.year = 1

上述的INI文件可以被读进Zend_Config对象：

$config = new Zend_Config_Ini('/path/to/config.ini', 'production');
$router = new Zend_Controller_Router_Rewrite();
$router->addConfig($config, 'routes');

在上面的例子中，我们告诉路由器去使用INI文件'routes'一节给它的路由。每个在这个节下的顶级键将用来定义路由名；上述例子定义了路由'archive'和'news'。每个路由接着要求，至少，一个'route'条目和一个或更多'defaults'条目；可选地，一个或更多'reqs'（'required'的简写）可能要求提供。总之，这些相对应的三个参数提供给Zend_Controller_Router_Route_Interface对象。一个选项键，'type'，可用来指定路由类的类型给特殊的路由；缺省地，它使用Zend_Controller_Router_Route。在上述例子中，'news'路由被定义来使用Zend_Controller_Router_Route_Static。

Subclassing the Router

标准的rewrite路由器应当最大限度提供你所需的功能；大多时候，为了通过已知的路由提供新的或修改的功能，你将只需要创建一个新的路由类型

那就是说，你可能想要用不同的路由范例。接口Zend_Controller_Router_Interface提供了需要最少的信息来创建路由器，并包含一个单个的方法。

interface Zend_Controller_Router_Interface
{
  /**
   * @param  Zend_Controller_Request_Abstract $request
   * @throws Zend_Controller_Router_Exception
   * @return Zend_Controller_Request_Abstract
   */
  public function route(Zend_Controller_Request_Abstract $request);
}

路由只发生一次：当请求第一次接收到系统。路由器的意图是基于请求的环境决定控制器、动作和可选的参数，并把它们发给请求。请求对象接着传递给派遣器。如果不可能映射一个路由到一个派遣令牌，路由器对请求对象就什么也不做。

请求对象
Zend_Controller
Zend Framework手册 中文版
分发器
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Controller
  • Zend_Controller 快速入门
  • Zend_Controller 基础
  • 前端控制器
  • 请求对象
  • 标准路由器
  • 分发器
  • 动作控制器
  • 动作助手
  • 响应对象
  • 插件
  • 使用传统的模块目录结构
  • MVC 异常


分发器 - Zend Framework Manual

标准路由器
Zend_Controller
Zend Framework手册 中文版
动作控制器

分发器

概述

分发是取得请求对象，提取其中的模块名，控制器名，动作名以及可选参数，然后实例化控制器并调用其中的动作的整过过程。如果其中的模块、控制器或者动作没能找到，将使用它们的默认值。Zend_Controller_Dispatcher_Standard指定每个控制器和动作的默认值为 index，模块的默认值为default，允许开发人通过setDefaultController()、setDefaultAction()和setDefaultModule()改变默认值设定。

Note: 缺省模块
 当创建模块程序，你可能也需要缺省模块的命名空间（缺省配置中，缺省模块没有命名空间）。从 1.5.0 开始，可以在前端控制器或你的派遣器里通过指定 prefixDefaultModule 为 true 来实现。

// 在你的前端控制器中：
$front->setParam('prefixDefaultModule', true);

// 在你的分发器中：
$dispatcher->setParam('prefixDefaultModule', true);
这允许你重定义一个已存在的模块为程序的缺省模块。

分发发生在前端控制器中的一个循环（loop）中。分发之前，前端控制器通过路由请求，找到用户指定的模块、控制器、动作和可选参数。然后进入分发循环，分发请求。

每次迭代（iteration）过程开始时，在请求对象中设置一个标志指示该动作已分发。如果在动作或者前/后分发（pre/postDispatch）插件重置了该标志，分发循环将继续下去并试图分发新的请求。通过改变请求中的控制器或者动作并重置已分发标志，开发人员可以定制执行一个请求链。

控制这种分发过程的动作控制器方法是_forward()；在任意的pre/postDispatch()或者动作中调用该方法，并传入动作、控制器、模块、以及可选的附加参数，就可以进入新的动作。

public function fooAction()
{
    // forward to another action in the current controller and module:
    $this->_forward('bar', null, null, array('baz' => 'bogus'));
}

public function barAction()
{
    // forward to an action in another controller:
    // FooController::bazAction(),
    // in the current module:
    $this->_forward('baz', 'foo', null, array('baz' => 'bogus'));
}

public function bazAction()
{
    // forward to an action in another controller in another module,
    // Foo_BarController::bazAction():
    $this->_forward('baz', 'bar', 'foo', array('baz' => 'bogus'));
}

子类化分发器

Zend_Controller_Front首先调用路由器找到请求中的第一个动作，然后进入分发循环，调用分发器分发动作。

分发器需要大量数据完成任务——它需要知道如何格式化控制器和动作的名称，到哪儿找到控制器类文件，模块名是否有效，以及基于其它可用信息判定请求是否能分发的API。

Zend_Controller_Dispatcher_Interface定义了下列所有分发器需要实现的方法。

interface Zend_Controller_Dispatcher_Interface
{
    /**
     * Format a string into a controller class name.
     *
     * @param string $unformatted
     * @return string
     */
    public function formatControllerName($unformatted);

    /**
     * Format a string into an action method name.
     *
     * @param string $unformatted
     * @return string
     */
    public function formatActionName($unformatted);

    /**
     * Determine if a request is dispatchable
     *
     * @param  Zend_Controller_Request_Abstract $request
     * @return boolean
     */
    public function isDispatchable(
        Zend_Controller_Request_Abstract $request
    );

    /**
     * Set a user parameter (via front controller, or for local use)
     *
     * @param string $name
     * @param mixed $value
     * @return Zend_Controller_Dispatcher_Interface
     */
    public function setParam($name, $value);

    /**
     * Set an array of user parameters
     *
     * @param array $params
     * @return Zend_Controller_Dispatcher_Interface
     */
    public function setParams(array $params);

    /**
     * Retrieve a single user parameter
     *
     * @param string $name
     * @return mixed
     */
    public function getParam($name);

    /**
     * Retrieve all user parameters
     *
     * @return array
     */
    public function getParams();

    /**
     * Clear the user parameter stack, or a single user parameter
     *
     * @param null|string|array single key or array of keys for
     *        params to clear
     * @return Zend_Controller_Dispatcher_Interface
     */
    public function clearParams($name = null);

    /**
     * Set the response object to use, if any
     *
     * @param Zend_Controller_Response_Abstract|null $response
     * @return void
     */
    public function setResponse(
        Zend_Controller_Response_Abstract $response = null
    );

    /**
     * Retrieve the response object, if any
     *
     * @return Zend_Controller_Response_Abstract|null
     */
    public function getResponse();

    /**
     * Add a controller directory to the controller directory stack
     *
     * @param string $path
     * @param string $args
     * @return Zend_Controller_Dispatcher_Interface
     */
    public function addControllerDirectory($path, $args = null);

    /**
     * Set the directory (or directories) where controller files are
     * stored
     *
     * @param string|array $dir
     * @return Zend_Controller_Dispatcher_Interface
     */
    public function setControllerDirectory($path);

    /**
     * Return the currently set directory(ies) for controller file
     * lookup
     *
     * @return array
     */
    public function getControllerDirectory();

    /**
     * Dispatch a request to a (module/)controller/action.
     *
     * @param  Zend_Controller_Request_Abstract $request
     * @param  Zend_Controller_Response_Abstract $response
     * @return Zend_Controller_Request_Abstract|boolean
     */
    public function dispatch(
        Zend_Controller_Request_Abstract $request,
        Zend_Controller_Response_Abstract $response
    );

    /**
     * Whether or not a given module is valid
     *
     * @param string $module
     * @return boolean
     */
    public function isValidModule($module);

    /**
     * Retrieve the default module name
     *
     * @return string
     */
    public function getDefaultModule();

    /**
     * Retrieve the default controller name
     *
     * @return string
     */
    public function getDefaultControllerName();

    /**
     * Retrieve the default action
     *
     * @return string
     */
    public function getDefaultAction();
}

不过大多数情况下，只需要简单地扩展抽象类Zend_Controller_Dispatcher_Abstract，其中已经定义好了上面的大部分方法。或者扩展Zend_Controller_Dispatcher_Standard类，基于标准分发器来修改功能。

需要子类化分发器的可能原因包括：期望在动作控制器中使用不同的类和方法命名模式，或者期望使用不同的分发方式，比如分发到控制器目录下的动作文件，而不是控制器类的动作方法。

标准路由器
Zend_Controller
Zend Framework手册 中文版
动作控制器
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Controller
  • Zend_Controller 快速入门
  • Zend_Controller 基础
  • 前端控制器
  • 请求对象
  • 标准路由器
  • 分发器
  • 动作控制器
  • 动作助手
  • 响应对象
  • 插件
  • 使用传统的模块目录结构
  • MVC 异常


动作控制器 - Zend Framework Manual

分发器
Zend_Controller
Zend Framework手册 中文版
动作助手

动作控制器

简介

Zend_Controller_Action是一个抽象类，当基于模型－视图－控制器（MVC）模式建立网站的时候，你可以用它来为和前端控制器使用一起来实现动作控制器。

为使用Zend_Controller_Action，你需要在实际的控制器类中把它子类化（或者为动作控制器创建你自己的基本类而使它子类化）。最基本的操作是子类化和创建对应于不同动作的动作方法，这些动作是你希望控制器来处理你的站点的动作。Zend_Controller的路由和派遣处理将在你的类里自动发现任何以'Action'结尾的方法作为潜在的控制器动作。

例如，你的类如下定义：

class FooController extends Zend_Controller_Action
{
    public function barAction()
    {
        // do something
    }

    public function bazAction()
    {
        // do something
    }
}

上述 FooController 类（控制器foo）定义了两个动作：bar和baz。

还有更多的可以被实现，例如定制初始化动作，如果没有动作（或者有个无效动作）被指定，缺省的动作被调用，派遣之前和之后的钩子，以及无数的助手方法。这章是动作控制器功能的一个总览。

Note: 缺省行为
 缺省地，前端控制器激活了ViewRenderer动作助手。这个助手负责把视图对象注入到控制器，同时解析（rendering）视图。通过下面方法之一，可以在动作控制器里禁止它：

class FooController extends Zend_Controller_Action
{
    public function init()
    {
        // 只是局部控制器；当初始化加载时，对这个控制器的所有动作有效：
        $this->_helper->viewRenderer->setNoRender(true);

        // 全局：
        $this->_helper->removeHelper('viewRenderer');

        // 也是全局，但需要和本地版本协作，以便繁殖这个控制器：
        Zend_Controller_Front::getInstance()->setParam('noViewRenderer', true);
    }
}
initView()、 getViewScript()、render()和renderScript() 都代理 ViewRenderer，除非助手不在助手经纪人（broker）里或noViewRenderer标志被设置。
通过设置ViewRenderer的noRender标记，可以简单地为一个独立的视图禁止解析（rendering）：
class FooController extends Zend_Controller_Action
{
    public function barAction()
    {
        // disable autorendering for this action only:
        $this->_helper->viewRenderer->setNoRender();
    }
}
禁止ViewRenderer的主要原因是如果你不需要视图对象或者如果你不通过视图脚本（例如，当使用动作控制器来司服网站服务协议如SOAP,XML-RPC或REST）来解析。大多数情况下，你不需要全局地禁止ViewRenderer，只选择性地在个别控制器或动作里禁止它。

对象初始化

虽然你可以总重写动作控制器的构造函数，我们不建议这么做。Zend_Controller_Action::__construct()执行一些重要的任务，如注册请求和响应对象，还有任何从前端控制器传来的invocation参数。如果你必须重写构造函数，别忘记调用parent::__construct($request, $response, $invokeArgs)。

更合适的方法来定制实例化是使用init()方法，它是在__construct()里的最后一个调用任务。例如，如果你想在实例化时连接数据库：

class FooController extends Zend_Controller_Action
{
    public function init()
    {
        $this->db = Zend_Db::factory('Pdo_Mysql', array(
            'host'     => 'myhost',
            'username' => 'user',
            'password' => 'XXXXXXX',
            'dbname'   => 'website'
        ));
    }
}

派遣前后的钩子

Zend_Controller_Action指定两个方法，preDispatch() 和postDispatch()，可能被调用来bookend一个请求的动作。这在很多场合都有用：例如在运行一个动作（通过调用preDispatch()里的_forward()，动作将被跳过）前校验认证和ACLs，或者在网站范围的模板里（postDispatch()）替换生成的内容。

访问器

无数的对象和变量与对象一起注册，并且每个都有访问器方法。

  • 请求对象：getRequest()可用来读取调用动作请求对象。

  • 响应对象: getResponse()可用来读取收集最终响应的响应对象。一些典型的调用看起来象这样：

    $this->getResponse()->setHeader('Content-Type', 'text/xml');
$this->getResponse()->appendBody($content);

  • 调用参数：前端控制器可能把参数传给路由器、派遣器和动作控制器。为了读取这些参数，可使用getInvokeArg($key)；另外，用getInvokeArgs()读取整个参数列表。

  • 请求参数：请求对象手机请求参数，如任何_GET 或 _POST 参数，或者指定在URL的路径信息里的用户参数。为了读取这些参数，可使用_getParam($key)或_getAllParams()。也可以用_setParam()来设置请求参数；当转发到另外的动作时这很有用。

    用_hasParam($key)来测试是否一个参数存在（对逻辑分支有用）。

    Note: _getParam()可带有一个可选的第二个参数，如果它不是空的，就包含一个缺省的值。用它在读取值之前来消除对_hasParam() 的调用：

    // Use default value of 1 if id is not set
$id = $this->_getParam('id', 1);

// Instead of:
if ($this->_hasParam('id') {
    $id = $this->_getParam('id');
} else {
    $id = 1;
}

视图集成

Zend_Controller_Action为视图继承提供了一个初步的灵活的机制。有两个方法来完成这个：initView() 和 render()；前者松散地加载$view public 属性，后者基于当前请求的动作来解析视图，它们使用目录层次来决定脚本路径。

视图初始化

initView()初始化视图对象。为了读取视图对象，render()调用initView()，但它可以在任何时候被初始化；缺省地，它用Zend_View对象来组装$view属性，但任何实现Zend_View_Interface的类可以使用。如果$view已经被初始化，它就简单地返回属性。

缺省的实现使用下面假设的目录结构：

applicationOrModule/
    controllers/
        IndexController.php
    views/
        scripts/
            index/
                index.phtml
        helpers/
        filters/

换句话说，视图脚本假定放在views/scripts/子目录，同时假定 views子目录还包含兄弟功能（助手和过滤器）。确定视图脚本名称和路径时，先以 views/scripts/作为基路径，然后加上以视图脚本对应控制器命名的目录。

解析（Rendering）视图

render() 有下列特征：has the following signature:

string render(string $action = null,
              string $name = null,
              bool $noController = false);

render()解析视图脚本。如果没有传递参数，它假定请求的脚本是[controller]/[action].phtml （.phtml是$viewSuffix属性的值）。为$action传递一个值将解析在[controller]子目录中的模板。为用[controller]重写，传递一个true值给$noController。最后，模板被解析到响应对象；如果你希望解析到一个在响应对象里指定的named segment，传递一个值给$name。

Note: 因为控制器和动作名字里可能包含分隔符如'_'、 '.' 和 '-'，当决定视图名字时，render()把它们规格化成 '-'.在内部，它使用派遣器的字和路径分隔符来做规格化。这样，对/foo.bar/baz-bat的请求将解析脚本foo-bar/baz-bat.phtml。如果动作方法包含camelCasing，记住当决定视图脚本文件名的时候，这将变成由'-'分隔的字。

一些例子：

class MyController extends Zend_Controller_Action
{
    public function fooAction()
    {
        // Renders my/foo.phtml
        $this->render();

        // Renders my/bar.phtml
        $this->render('bar');

        // Renders baz.phtml
        $this->render('baz', null, true);

        // Renders my/login.phtml to the 'form' segment of the
        // response object
        $this->render('login', 'form');

        // Renders site.phtml to the 'page' segment of the response
        // object; does not use the 'my/' subirectory
        $this->render('site', 'page', true);
    }

    public function bazBatAction()
    {
        // Renders my/baz-bat.phtml
        $this->render();
    }
}

实用方法

除了访问器和视图继承方法，在动作方法内部里，Zend_Controller_Action有若干实用方法来执行普通的任务（或在派遣的前后）。

  • _forward($action, $controller = null, $module = null, array $params = null) ：执行另外一个动作。如果在preDispatch()里调用，当前请求的动作将被跳过来支持新的动作。否则，在当前动作被处理之后，在_forward()请求的动作将被执行。

  • _redirect($url, array $options = array())：重定向到另外一个地方。这个方法用URL和一组可选的选项。缺省地，它执行HTTP 302 重定向。

    选项可包括一个或多个下面这些：

    • exit:是否立即退出。如果被请求，它将干净地关闭任何打开的会话和执行重定向。

      可以用setRedirectExit()访问器在控制器里全局地设置这个选项。

    • prependBase:是否预先考虑基础URL和URL提供的请求对象一起注册。

      使用setRedirectPrependBase()访问器，在控制器里全局地设置这个选项。

    • code:在重定向时要用什么HTTP代码。缺省使用302；可以用从301到306之间的任何代码。

      使用setRedirectCode()访问器，在控制器里全局地设置这个选项。

继承（Subclassing）动作控制器

为了创建动作控制器，设计上，Zend_Controller_Action 必须被继承。至少，需要定义控制器可能调用的动作方法。

除了为web应用程序创建有用的函数外，你可能发现在不同的控制器里重复同样的设置和实用方法；如果这样，创建一个继承（extends）Zend_Controller_Action 的基础类可能会解决问题。

Example #1 如何处理不存在的动作

如果控制器的请求包括一个未定义的动作方法，Zend_Controller_Action::__call()将被调用。__call()当然是PHP中用来重载方法的魔术方法。

缺省地，这个方法抛出一个Zend_Controller_Action_Exception 来表明在控制器里没有发现要求的方法。如果要求的方法以'Action'结尾，就假设一个动作被请求并且不存在；这样的错误导致带有代码为 404 的异常。所有其它方法导致带有代码为 500 的异常。这使你很容易地在错误句柄里区分是页面没有发现还是程序错误。

如果想执行其它操作，你应该重写这个函数。例如，如果你想显示错误信息，可以象下面这样来写：

class MyController extends Zend_Controller_Action
{
    public function __call($method, $args)
    {
        if ('Action' == substr($method, -6)) {
            // If the action method was not found, render the error
            // template
            return $this->render('error');
        }

        // all other methods throw an exception
        throw new Exception('Invalid method "'
                            . $method
                            . '" called',
                            500);
    }
}

另外的可能性就是你可能想转发到缺省控制页面：

class MyController extends Zend_Controller_Action
{
    public function indexAction()
    {
        $this->render();
    }

    public function __call($method, $args)
    {
        if ('Action' == substr($method, -6)) {
            // If the action method was not found, forward to the
            // index action
            return $this->_forward('index');
        }

        // all other methods throw an exception
        throw new Exception('Invalid method "'
                            . $method
                            . '" called',
                            500);
    }
}

为了定制控制器，除了重写__call()以外，本章前面说涉及的初始化、实用程序、访问器、视图和派遣钩子等方法都可以被重写。作为例子，如果把视图对象保存到注册表里，你可能想用象下面的代码来修改initView()：

abstract class My_Base_Controller extends Zend_Controller_Action
{
    public function initView()
    {
        if (null === $this->view) {
            if (Zend_Registry::isRegistered('view')) {
                $this->view = Zend_Registry::get('view');
            } else {
                $this->view = new Zend_View();
                $this->view->setBasePath(dirname(__FILE__) . '/../views');
            }
        }

        return $this->view;
    }
}

很希望你能从这章的信息里发现这个特别的组件的灵活性并且用到你的程序和网站里。

分发器
Zend_Controller
Zend Framework手册 中文版
动作助手
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Controller
  • Zend_Controller 快速入门
  • Zend_Controller 基础
  • 前端控制器
  • 请求对象
  • 标准路由器
  • 分发器
  • 动作控制器
  • 动作助手
  • 响应对象
  • 插件
  • 使用传统的模块目录结构
  • MVC 异常


动作助手 - Zend Framework Manual

动作控制器
Zend_Controller
Zend Framework手册 中文版
响应对象

动作助手

介绍

动作助手可以向任何Zend_Controller_Action的衍生动作控制器中，即时的加入功能(runtime and/or on-demand functionality)，以使得增加公共的动作控制器功能时，尽量减少衍生动作控制器类的必要。

动作助手有多种使用方式。动作助手使用了一套经纪系统(brokerage system)，与Zend_View_Helper中使用的，也就是Zend_Controller_Plugin的经纪系统类似。动作助手（like Zend_View_Helper）在需要调用时加载，可以在请求的时候(bootstrap)或者动作控制器创建的时候(init())实例化。要充分了解这些细节，请阅读下面的章节。

初始化助手

根据需求以及助手的功能，可有几种不同的初始化方式。

助手经纪人(broker)存储在Zend_Controller_Action的 $_helper成员中，可以使用经纪人来获取或者调用助手。以下是操作方法：

  • 显式的调用getHelper()方法。简单的传入助手名字，就可以返回助手对象。

    $flashMessenger = $this->_helper->getHelper('FlashMessenger');
$flashMessenger->addMessage('We did something in the last request');

  • 使用助手经纪人的__get()方法，就像获取经纪人的成员属性一样获取助手。

    $flashMessenger = $this->_helper->FlashMessenger;
$flashMessenger->addMessage('We did something in the last request');

  • 最后，大部分动作助手实现了direct()方法，它将调用助手的一个特定的，默认的方法。以FlashMessenger为例，它调用了方法addMessage()：

    $this->_helper->FlashMessenger('We did something in the last request');

Note: 上面的例子在功能上是等价的。

也可以显式的实例化助手。如果你要在动作控制器之外使用助手，或者给助手经纪人传入一个助手供所有的动作使用，你可能希望直接这么做。实例化助手和实例化其他PHP类的方法一样。

助手经纪人

Zend_Controller_Action_HelperBroker处理注册助手对象和助手路径，即时的获取助手等细节。

使用addHelper来注册助手：

Zend_Controller_Action_HelperBroker::addHelper($helper);

实例化助手并传入经纪人有点耗费时间和资源，不过addPrefix()和addPath()两个方法能够很容易的自动完成这些工作：

  • addPrefix()方法带有一个类前缀参数，用来加入自定义助手类的路径。它假定前缀遵循Zend Framework的类命名惯例。

    // Add helpers prefixed with My_Action_Helpers in My/Action/Helpers/
Zend_Controller_Action_HelperBroker::addPrefix('My_Action_Helpers');

  • addPath()方法第一个参数为一个目录，第二个为类前缀(默认为'Zend_Controller_Action_Helper')。用来将自己的类前缀映射到指定的目录。

    // Add helpers prefixed with Helper in Plugins/Helpers/
Zend_Controller_Action_HelperBroker::addPath('./Plugins/Helpers',
                                             'Helper');

这些方法是静态的，因而可以根据需要在控制器链中的任何位置调用动态的加载助手。

使用hasHelper($name)方法来判定助手经纪人中是否存在某助手，$name是助手的短名称（去掉前缀的）：

// Check if 'redirector' helper is registered with the broker:
if (Zend_Controller_Action_HelperBroker::hasHelper('redirector')) {
    echo 'Redirector helper registered';
}

从助手经纪人中获取助手有两个静态方法：getExistingHelper() 和 getStaticHelper() 。getExistingHelper()将获取助手仅当它以前调用过或者显性地通过助手经纪人注册过，否则就抛出一个异常。getStaticHelper() 的做法和getExistingHelper()一样，但如果还没有注册助手堆栈，它将尝试初始化助手，为获取你要配置的的助手，getStaticHelper()是一个好的选择。

两个方法都带一个参数，$name，它是助手的短名称（去掉前缀）。

// Check if 'redirector' helper is registered with the broker, and fetch:
if (Zend_Controller_Action_HelperBroker::hasHelper('redirector')) {
    $redirector =
        Zend_Controller_Action_HelperBroker::getExistingHelper('redirector');
}

// Or, simply retrieve it, not worrying about whether or not it was
// previously registered:
$redirector =
    Zend_Controller_Action_HelperBroker::getStaticHelper('redirector');
}

最后，使用removeHelper($name)来删除助手经纪人中的某个助手，$name是助手的短名称。

// Conditionally remove the 'redirector' helper from the broker:
if (Zend_Controller_Action_HelperBroker::hasHelper('redirector')) {
    Zend_Controller_Action_HelperBroker::removeHelper('redirector')
}

内建的动作助手

Zend Framework 默认包含若干个动作助手：AutoComplete 自动响应 AJAX 的自动完成；ContextSwitch 和 AjaxContext 为你的动作提供替代响应格式；FlashMessenger 用来处理Flash Messenger会话；Json 用来解码和发送 JSON 响应；Redirector 提供另一种实现方式，帮助程序重定向到内部或者外部页面；ViewRenderer 自动的完成在控制器内建立视图对象并渲染视图的过程。

动作堆栈（助手）

动作堆栈助手允许把请求压到动作堆栈前端控制器插件，有效地帮助你在请求期间创建一个动作队列来执行。（动作堆栈）助手允许你通过指定新的请求对象或通过“动作/控制器/模块”集合来添加动作。

Note: 调用动作堆栈助手来初始化动作堆栈插件
 调用动作堆栈 助手暗中注册动作堆栈 插件 -- 这就意味着你不需要显性地注册动作堆栈 插件来用这个功能。

Example #1 用动作、控制器和模块名来添加一个任务

经常地，仅仅指定动作、控制器和模块（和可选的参数）最简单，和调用Zend_Controller_Action::_forward()一样：

class FooController extends Zend_Controller_Action
{
    public function barAction()
    {
        // Add two actions to the stack
        // Add call to /foo/baz/bar/baz
        // (FooController::bazAction() with request var bar == baz)
        $this->_helper->actionStack('baz',
                                    'foo',
                                    'default',
                                    array('bar' => 'baz'));

        // Add call to /bar/bat
        // (BarController::batAction())
        $this->_helper->actionStack('bat', 'bar');
    }
}

Example #2 使用请求对象添加一个任务

有时候请求对象的OOP本性很有用；你也可以传递这样一个对象给动作堆栈助手。

class FooController extends Zend_Controller_Action
{
    public function barAction()
    {
        // Add two actions to the stack
        // Add call to /foo/baz/bar/baz
        // (FooController::bazAction() with request var bar == baz)
        $request = clone $this->getRequest();
        // Don't set controller or module; use current values
        $request->setActionName('baz')
                ->setParams(array('bar' => 'baz'));
        $this->_helper->actionStack($request);

        // Add call to /bar/bat
        // (BarController::batAction())
        $request = clone $this->getRequest();
        // don't set module; use current value
        $request->setActionName('bat')
                ->setControllerName('bar');
        $this->_helper->actionStack($request);
    }
}

AutoComplete

许多 AJAX javascript 函数库提供了以潜在地匹配结果的选择列表作为用户类别显示的自动完成。AutoComplete 助手简化返回可接受的响应给这样的方法。

因为并非所有的 JS 库用同样的方法实现自动完成，AutoComplete 助手提供了一些必要的基本的摘要函数给这些库并对个别库提供了具体实现。返回类型一般是 JSON 字符串数组、JSON 数组的数组 （每个成员的数组是一个用于创建选择列表的元数据（metadata）的关联数组） 或 HTML。

每个实现的基本用法都一样：

class FooController extends Zend_Controller_Action
{
    public function barAction()
    {
        // Perform some logic...

        // Encode and send response;
        $this->_helper->autoCompleteDojo($data);

        // Or explicitly:
        $response = $this->_helper->autoCompleteDojo
                                  ->sendAutoCompletion($data);

        // Or simply prepare autocompletion response:
        $response = $this->_helper->autoCompleteDojo
                                  ->prepareAutoCompletion($data);
    }
}

缺省地，自动完成做这些工作：

  • 关闭布局（layouts）和视图解析器（ViewRenderer）。

  • 设置合适的响应头。

  • 用编码的/格式化的自动完成数据设置响应体。

  • 发送响应。

可用的助手方法包括：

  • disableLayouts() 用来关闭布局和视图解析器。一般地，在 prepareAutoCompletion() 里调用它。

  • encodeJson($data, $keepLayouts = false) 给 JSON 编码，可选打开或关闭布局。一般地，在 prepareAutoCompletion() 里调用它。

  • prepareAutoCompletion($data, $keepLayouts = false) 用来为具体实现以响应格式准备数据，可选地打开或关闭布局，返回值因不同的实现而不同。

  • sendAutoCompletion($data, $keepLayouts = false) 用来为具体实现发送响应格式的数据，它调用 prepareAutoCompletion()，然后发送响应。

  • 当把助手作为助手代理的方法来调用，使用 direct($data, $sendNow = true, $keepLayouts = false) 。The $sendNow flag 用来决定是否分别调用 sendAutoCompletion() 或 prepareAutoCompletion()。

目前 AutoComplete 支持 Dojo 和 Scriptaculous AJAX 库。

AutoCompletion with Dojo

Dojo 本身没有 AutoCompletion 小部件，但有两个小部件可以执行 AutoCompletion：ComboBox 和 FilteringSelect。对于这两者，都要求实现 QueryReadStore 的数据存储，关于这话题的更多信息参见 » dojo.data 文档。

在 Zend Framework 中，可以传递简单的索引的数组给 AutoCompleteDojo 助手，它将返回一个适合和这样一个存储一起使用的 JSON 响应：

// within a controller action:
$this->_helper->autoCompleteDojo($data);

Example #3 AutoCompletion with Dojo Using Zend MVC

AutoCompletion with Dojo 通过 Zend MVC 需要若干事项：为你想要 AutoCompletion 的 ComboBox 生成一个表单对象，服务于 AutoCompletion 结果的控制器动作，生成定制的 QueryReadStore 来连接到 AutoCompletion 动作和 javascript 的生成用于在服务器端初始化 AutoCompletion。

首先，看一下必需的 javascript 。Dojo 为生成 OOP javascript 提供一个完整的框架，很像 Zend Framework 对于 PHP。它的部分功能是使用目录等级结构生成假的命名空间（pseudo-namespaces ）。 我们将在和 Dojo 同一级目录创建一个 'custom' 目录，那是 Dojo 发行的一部分。 在目录里面，我们将创建 javascript 文件，TestNameReadStore.js 带有以下内容：

dojo.provide("custom.TestNameReadStore");
dojo.declare("custom.TestNameReadStore", dojox.data.QueryReadStore, {
    fetch:function (request) {
        request.serverQuery = { test:request.query.name };
        return this.inherited("fetch", arguments);
    }
});

该类是 Dojo 自己的 QueryReadStore 的扩展，QueryReadStore 是一个抽象类。我们简单地通过请求定义一个方法，并把它分配给 'test' 元素。

下一步，为我们想要的 AutoCompletion 生成表单元素：

class TestController extends Zend_Controller_Action
{
    protected $_form;

    public function getForm()
    {
        if (null === $this->_form) {
            $this->_form = new Zend_Form();
            $this->_form->setMethod('get')
                ->setAction(
                    $this->getRequest()->getBaseUrl() . '/test/process'
                )
                ->addElements(array(
                    'test' => array('type' => 'text', 'options' => array(
                        'filters'        => array('StringTrim'),
                        'dojoType'       => array('dijit.form.ComboBox'),
                        'store'          => 'testStore',
                        'autoComplete'   => 'false',
                        'hasDownArrow'   => 'true',
                        'label' => 'Your input:',
                    )),
                    'go' => array('type' => 'submit',
                                  'options' => array('label' => 'Go!'))
                ));
        }
        return $this->_form;
    }
}

这里，我们用 'test' 和 'go' 方法生成表单。'test' 方法添加若干特别的 Dojo 专用的属性：dojoType、 store、 autoComplete 和 hasDownArrow。dojoType 用来指示我们在生成 comboBox，并且我们将把它链接到 'testStore' 的数据存储（键 'store'）－－ 稍后还有更多。指定 'autoComplete' 作为 false 告诉 Dojo 不要自动选择第一个匹配，但是要显示一个匹配列表。最后，'hasDownArrow' 生成和选择 box 类似的向下箭头，这样我们可以显示和隐藏匹配。

让我们添加一个方法来显示表单，和处理 AutoCompletion 的结束点：

class TestController extends Zend_Controller_Action
{
    // ...

    /**
     * Landing page
     */
    public function indexAction()
    {
        $this->view->form = $this->getForm();
    }

    public function autocompleteAction()
    {
        if ('ajax' != $this->_getParam('format', false)) {
            return $this->_helper->redirector('index');
        }
        if ($this->getRequest()->isPost()) {
            return $this->_helper->redirector('index');
        }

        $match = trim($this->getRequest()->getQuery('test', ''));

        $matches = array();
        foreach ($this->getData() as $datum) {
            if (0 === strpos($datum, $match)) {
                $matches[] = $datum;
            }
        }
        $this->_helper->autoCompleteDojo($matches);
    }
}

在 autocompleteAction() 中我们做许多事情。首先，我们注意确保我们有个 post 请求，并且有个 'format' 参数的值为 'ajax'；这样减少欺骗查询给动作。接着，我们检查 'test' 参数，并和我们的数据比较。（我在这里故意忽略了 getData() 的实现 －－ 它可以是任何数据源）。最后，发送匹配给 AutoCompletion 助手。

既然我们在后台有了所有的东西，来看一下在视图脚本中对于 landing 页面我们需要提交什么。 首先，我们需要设置数据存储，然后解析表单，最后确保合适的 Dojo 库被加载 －－包括定制的数据存储。来看看视图脚本，步骤在注释里：

<? // setup our data store: ?>
<div dojoType="custom.TestNameReadStore" jsId="testStore"
    url="<?= $this->baseUrl() ?>/unit-test/autocomplete/format/ajax"
    requestMethod="get"></div>

<? // render our form: ?>
<?= $this->form ?>

<? // setup Dojo-related CSS to load in HTML head: ?>
<? $this->headStyle()->captureStart() ?>
@import "<?= $this->baseUrl() ?>/javascript/dijit/themes/tundra/tundra.css";
@import "<?= $this->baseUrl() ?>/javascript/dojo/resources/dojo.css";
<? $this->headStyle()->captureEnd() ?>

<? // setup javascript to load in HTML head, including all required
   // Dojo libraries: ?>
<? $this->headScript()
        ->setAllowArbitraryAttributes(true)
        ->appendFile($this->baseUrl() . '/javascript/dojo/dojo.js',
            'text/javascript',
            array('djConfig' => 'parseOnLoad: true'))
        ->captureStart() ?>
djConfig.usePlainJson=true;
dojo.registerModulePath("custom","../custom");
dojo.require("dojo.parser");
dojo.require("dojox.data.QueryReadStore");
dojo.require("dijit.form.ComboBox");
dojo.require("custom.TestNameReadStore");
<? $this->headScript()->captureEnd() ?>

注意对视图助手的调用如 headStyle 和 headScript，它们是占位符，我们可以在布局视图脚本的 HTML 头中解析。

现在所有的 Dojo AutoCompletion 开始工作了。

AutoCompletion with Scriptaculous

» Scriptaculous 需要一个特定格式的 HTML 响应。

和这个库一起使用的助手是 'AutoCompleteScriptaculous'，给它提供一个数据数组，这个助手将生成兼容于 Ajax.Autocompleter 的 HTML 响应。

ContextSwitch and AjaxContext

ContextSwitch 动作助手用来使在请求后返回不同的响应格式变得容易。AjaxContext 助手是 ContextSwitch 的特别版本，用来返回响应到 XmlHttpRequests。

你必须在关于动作能够响应哪个上下文（context）的控制器中打开（enable）其中一个。如果一个进来的请求对给定的动作指出一个有效的上下文，助手将做：

  • 如果布局被打开，则关闭它。

  • 设置一个备用的视图后缀，为上下文有效地请求一个分离的视图脚本。

  • 为期望的上下文发送适当的响应头。

  • 可选地调用特别的回调（callback）来设置上下文和/或执行处理后的任务。

例子，考虑下列的控制器：

class NewsController extends Zend_Controller_Action
{
    /**
     * Landing page; forwards to listAction()
     */
    public function indexAction()
    {
        $this->_forward('list');
    }

    /**
     * List news items
     */
    public function listAction()
    {
    }

    /**
     * View a news item
     */
    public function viewAction()
    {
    }
}

我们想让 listAction() 也支持 XML 格式，不用创建一个不同的动作，我们可以提示它可以返回 XML 响应：

class NewsController extends Zend_Controller_Action
{
    public function init()
    {
        $contextSwitch = $this->_helper->getHelper('contextSwitch');
        $contextSwitch->addActionContext('list', 'xml')
                      ->initContext();
    }

    // ...
}

这将完成：

  • 设置 'Content-Type' 响应头为 'text/xml'.

  • 修改视图后缀为 'xml.phtml' （或者，如果你使用另外的视图后缀，'xml.[你的后缀]'）。

现在你需要创建一个新的视图脚本 'news/list.xml.phtml'，它将创建和解析 XML。

为决定一个请求是否应该初始化一个上下文开关（context switch），这个助手检查在请求对象理的令牌。缺省地，它寻找一个 'format' 参数，尽管这是可配置的。这意味着，在大多数情况下，为触发一个上下文开关，你可以添加一个 'format' 参数给你的请求：

  • 通过 URL 参数：/news/list/format/xml （回忆一下，缺省路由模式（schema）允许在动作后跟随任意的键/值对）

  • 通过 GET 参数：/news/list?format=xml

ContextSwitch 允许指定任意的上下文，包括需要修改后缀的、任何应该被发送的响应头和任意的用来初始化和善后的回调（callback）。

缺省可用的上下文

缺省地，ContextSwitch 助手的两个上下文可用：json 和 xml。

  • JSON. JSON 上下文设置 'Content-Type' 响应头为 'application/json'，设置视图脚本后缀为 'json.phtml'。

    缺省地，不需要视图脚本，它将系列化所有的视图变量，立即发出 JSON 响应。

    通过关闭 auto-JSON serialization 可禁止这个行为：

    $this->_helper->contextSwitch()->setAutoJsonSerialization(false);

  • XML. XML 上下文设置 'Content-Type' 响应头为 'text/xml'，设置视图脚本后缀为 'xml.phtml'。你需要为这个上下文创建新的视图脚本。

创建定制的上下文

有时候，缺省的上下文不够用，例如你需要返回 YAML，或系列化 PHP、RSS 或 ATOM feed 等等，ContextSwitch 正是你需要的东西。

最容易的添加新的上下文的办法是通过 addContext() 方法。这个方法带有两个参数：上下文的名称和一个规范（specification）数组，规范应当包含下列中的一个或多个：

  • suffix: 当在视图解析器里注册时，预先准备的缺省的视图后缀。

  • headers: 作为响应的一部分发送的头/值（header/value）对的数组。

  • callbacks: 数组，包含一个或更多键 'init' 或 'post'，指向有效的可用于上下文和善后处理的 PHP 回调（callback）。

    回调的初始化发生在当 ContextSwitch 检测到上下文时，你可以用它来执行任意的应该发生的逻辑。作为例子，当 auto-JSON serialization 是 on 的时候，JSON 上下文使用回调来关闭视图解析器（ViewRenderer）。

    善后处理（post processing）发生在动作的 postDispatch() 程序期间，可用来执行任意的逻辑。作为例子，JSON 上下文使用回调（callback）来决定是否 auto-JSON serialization 是 on；如果是，它系列化视图变量到 JSON 和 发送响应，如果不是，它重新打开（re-enable）视图解析器（ViewRenderer）。

和上下文交互作用的方法：

  • addContext($context, array $spec): 添加新的上下文，如果上下文存在，抛出一个异常。

  • setContext($context, array $spec): 添加新的上下文或重写一个已存在的上下文，和 addContext() 使用相同的规范（specification）。

  • addContexts(array $contexts): 一次添加多个上下文。$contexts 应当是上下文/规范（context/specification）对的数组。如果任何一个上下文存在，就抛出异常。

  • setContexts(array $contexts): 添加和重写存在的上下文（多于一个），和 addContexts() 使用相同的规范。

  • hasContext($context): 如果上下文存在，返回 true，否则返回 false。

  • getContext($context): 通过名称来获取一个单个的上下文，返回一个遵循用于 addContext() 的规范的数组。

  • getContexts(): 获取所有的上下文，返回上下文/规范对的数组。

  • removeContext($context): 通过名称来清除一个单个的上下文，成功返回 true，如果没有发现上下文返回 false。

  • clearContexts(): 清除所有上下文。

为每个动作设置上下文

有两个设置可用的上下文的机制：或者在控制器里手工创建数组，或者使用在 ContextSwitch 里的方法来装配它们。

添加动作/上下文关系的基本方法是 addActionContext() 。它有两个参数：上下文被添加到的动作和上下文的名称或上下文数组的其中之一。作为例子，考虑下列的控制器类：

class FooController extends Zend_Controller_Action
{
    public function listAction()
    {
    }

    public function viewAction()
    {
    }

    public function commentsAction()
    {
    }

    public function updateAction()
    {
    }
}

假如我们想添加 XML 上下文到 'list'动作、XML 和 JSON 上下文到 'comments' 动作，可以在 init() 方法中完成：

class FooController extends Zend_Controller_Action
{
    public function init()
    {
        $this->_helper->contextSwitch()
             ->addActionContext('list', 'xml')
             ->addActionContext('comments', array('xml', 'json'))
             ->initContext();
    }
}

另外，还可以定义数组属性 $contexts：

class FooController extends Zend_Controller_Action
{
    public $contexts = array(
        'list'     => array('xml'),
        'comments' => array('xml', 'json')
    );

    public function init()
    {
        $this->_helper->contextSwitch()->initContext();
    }
}

上述不但缺少周密考虑，而且有潜在的错误。

下面的方法可用来构造上下文映射：

  • addActionContext($action, $context): 标记一个或多个可用的上下文给一个动作，如果映射已经存在，就追加到那些映射中。$context 可以是一个单个的上下文，或者是一个上下文数组。

    一个上下文的 true 值将标记所有可用的上下文给动作。

    一个 $context 的空值将关闭（disable）所有给定动作的上下文。

  • setActionContext($action, $context): 标记一个或多个上下文对动作可用，如果映射已经存在，它就替换它们。$context 可以是一个单个的上下文，或者是一个上下文数组。

  • addActionContexts(array $contexts): 一次性添加若干动作/上下文对，$contexts 是动作/上下文对的关联数组。它代理 addActionContext()，意味着如果那些动作/上下文对存在，就追加之。

  • setActionContexts(array $contexts): 和 addActionContexts() 一样，但重写已存在的动作/上下文对。

  • hasActionContext($action, $context): 决定一个特定的动作是否有一个给定的上下文。

  • getActionContexts($action = null): 返回或者给定动作的所有上下文，或者所有动作/上下文对。

  • removeActionContext($action, $context): 从给定动作中清除一个或多个上下文。$context 可以是一个单个的上下文，或者是一个上下文数组。

  • clearActionContexts($action = null): 从给定动作或者从有上下文的动作中清除所有上下文。

初始化上下文开关

为初始化上下文开关，需要在动作控制器中调用 initContext()：

class NewsController extends Zend_Controller_Action
{
    public function init()
    {
        $this->_helper->contextSwitch()->initContext();
    }
}

在某些情况下，你想强制使用上下文，例如，如果上下文开关是激活状态，你只想用 XML 上下文，可以通过传递上下文给 initContext() 来完成：

$contextSwitch->initContext('xml');

另外的功能

用来改变 ContextSwitch 助手行为的方法包括：

  • setAutoJsonSerialization($flag): 缺省地，JSON 上下文将系列化任何视图变量给 JSON 符号并把它作为响应返回。如果想创建自己的响应，你需要关闭它，这需要在调用 initContext() 之前来完成。

    $contextSwitch->setAutoJsonSerialization(false);
$contextSwitch->initContext();

    用 getAutoJsonSerialization() 来获取 flag 的值。

  • setSuffix($context, $suffix, $prependViewRendererSuffix): 用这个方法，你可以为给定的上下文指定一个不同的后缀。第三个参数用来指示是否用新的后缀预先准备当前视图解析器，这个 flag 缺省为打开。

    传递空值给后缀将导致只有视图解析器的后缀被使用。

  • addHeader($context, $header, $content): 为给定的上下文添加一个响应头，$header 是头的名称，$content 是为这个头传递的值。

    每个上下文可以有多个头，addHeader() 把另外的头添加到头的堆栈。

    如果为上下文指定的 $header 已经存在，就抛出一个异常。

  • setHeader($context, $header, $content): setHeader() 和 addHeader() 一样，但它允许重写已经存在的上下文的头。

  • addHeaders($context, array $headers): 一次性添加多个头到给定的上下文，代理 addHeader()，如果头已经存在，将抛出异常。$headers 是一个头/上下文对的数组。

  • setHeaders($context, array $headers.): 象 addHeaders() 一样，但代理 setHeader()，允许重写已存在的头。

  • getHeader($context, $header): 获取给定上下文的头的值，如果没有发现返回 null。

  • removeHeader($context, $header): 清除一个单个的给定上下文的头。

  • clearHeaders($context, $header): 清除所有给定上下文的头。

  • setCallback($context, $trigger, $callback): 为给定的上下文在给定的触发器设置回调（callback），触发器或者是 'init'，或者是 'post'（指明回调将被在上下文初始化时或者派遣后（postDispatch）调用）。 $callback 应当是一个有效的 PHP 回调。

  • setCallbacks($context, array $callbacks): 为给定的上下文设置多个回调，$callbacks 应当是触发器/回调对。事实上，最常用的可注册的回调有两个：一个为初始化用的，一个是做善后处理。

  • getCallback($context, $trigger): 在给定的上下文中从给定的触发器中获取一个回调。

  • getCallbacks($context): 从给定的上下文获取所有的回调，返回一个触发器/回调对数组。

  • removeCallback($context, $trigger): 从给定的触发器和上下文清除一个回调。

  • clearCallbacks($context): 为给定的上下文清除所有的回调。

  • setContextParam($name): 设置请求参数来检查什么时候决定上下文开关是否已经请求，缺省值为 'format'，但这个访问器可以用来设置一个备用的值。

    getContextParam() 用来获取当前的值。

  • setAutoDisableLayout($flag): 缺省地，当上下文开关出现，布局是关闭的；这是因为一般布局将只用来返回正常的相应，对备用的（alternate）上下文没有意义。然而，如果想使用布局（也许你对新的上下文有个布局），你可以通过传递一个 false 的值给 setAutoDisableLayout() 来改变它的行为。这应当 在 调用 initContext() 之前 来做。

    用访问器 getAutoDisableLayout() 来获取这个 flag 的值。

  • getCurrentContext() 可用来确定什么上下文被检测到，如果有的话。如果没有上下文开关发生，或者在调用 initContext() 之前调用它，则返回 null。

AjaxContext 函数

AjaxContext 助手继承 ContextSwitch，所有 ContextSwitch 函数列表对它也有效，只是有些小小的不同。

首先，它为确定上下文使用不同的动作控制器属性 － $ajaxable。这样你就可以对 AJAX 和 普通的 HTTP 请求使用不同的上下文。AjaxContext 的各种各样 *ActionContext*() 方法将写到这个属性。

其次，由请求对象的 isXmlHttpRequest() 方法来确定，它只有在 XmlHttpRequest 出现后才触发。这样，如果上下文参数 （'format'）在请求中传递，但请求没有做成 XmlHttpRequest，不会触发上下文开关。

第三，AjaxContext 添加另外的上下文 － HTML。在这个上下文中，为了区别这个上下文和普通的请求，它设置后缀为 'ajax.phtml'。没有另外的头返回。

Example #4 允许动作响应 Ajax 的请求

在下面的例子中，我们允许对动作 'view'、 'form' 和 'process' 的请求响应 AJAX 的请求。在头两个例子 'view' 和 'form'，返回不更新页面的 HTML 片段；在最后的例子，返回 JSON。

class CommentController extends Zend_Controller_Action
{
    public function init()
    {
        $ajaxContext = $this->_helper->getHelper('AjaxContext');
        $ajaxContext->addActionContext('view', 'html')
                    ->addActionContext('form', 'html')
                    ->addActionContext('process', 'json')
                    ->initContext();
    }

    public function viewAction()
    {
        // Pull a single comment to view.
        // When AjaxContext detected, uses the comment/view.ajax.phtml
        // view script.
    }

    public function formAction()
    {
        // Render the "add new comment" form.
        // When AjaxContext detected, uses the comment/form.ajax.phtml
        // view script.
    }

    public function processAction()
    {
        // Process a new comment
        // Return the results as JSON; simply assign the results as
        // view variables, and JSON will be returned.
    }
}

在客户端，AJAX 库将请求终点 '/comment/view'、 '/comment/form' 和 '/comment/process'，并传递 'format' 参数：'/comment/view/format/html'、'/comment/form/format/html' 和 '/comment/process/format/json'。（或者你可以通过查询字符串（ query string） 传递参数，如："?format=json"）

假定你的库传递 'X-Requested-With:XmlHttpRequest'头，这些动作将返回适当的响应格式。

FlashMessenger

简介

FlashMessenger助手允许你传递用户可能需要在下个请求看到的消息。为实现它，FlashMessenger使用Zend_Session_Namespace来存储消息以备将来或下个请求来读取。如果你计划使用Zend_Session或者Zend_Session_Namespace，在引导文件里用Zend_Session::start()初始化，的确是个好主意。（参见Zend_Session文档有更多的关于它的用法的细节。）

Basic Usage Example

下面的例子展示flash messenger最基本的用法。当动作/some/my 被调用，它添加flash message "Record Saved!"，随后的对动作/some/my-next-request的请求将读取它（并也这样删除它）。

class SomeController extends Zend_Controller_Action
{
    /**
     * FlashMessenger
     *
     * @var Zend_Controller_Action_Helper_FlashMessenger
     */
    protected $_flashMessenger = null;

    public function init()
    {
        $this->_flashMessenger =
            $this->_helper->getHelper('FlashMessenger');
        $this->initView();
    }

    public function myAction()
    {
        /**
         * default method of getting
         * Zend_Controller_Action_Helper_FlashMessenger instance
         * on-demand
         */
        $this->_flashMessenger->addMessage('Record Saved!');
    }

    public function myNextRequestAction()
    {
        $this->view->messages = $this->_flashMessenger->getMessages();
        $this->render();
    }
}

JSON

当处理期望数据表响应的 AJAX 请求，JSON 响应迅速变成选择的响应。JSON 可以立即在客户端被解析，从而快速执行。

JSON 动作助手完成以下任务：

  • 如果布局是打开（enabled）的，则关闭（disable）它。

  • 如果视图解析器（ViewRenderer）是打开的，则关闭它。

  • 设置 'Content-Type' 响应头为 'application/json'。

  • 缺省地，不需要等待动作执行完成，立即返回响应。

用法很简单：或者把它作为助手代理的方法来调用，或者调用 encodeJson() 和 sendJson() 方法的其中之一：

class FooController extends Zend_Controller_Action
{
    public function barAction()
    {
        // do some processing...
        // Send the JSON response:
        $this->_helper->json($data);

        // or...
        $this->_helper->json->sendJson($data);

        // or retrieve the json:
        $json = $this->_helper->json->encodeJson($data);
    }
}

Note: 保持布局 （Keeping Layouts）
 如果你为 JSON 响应有分离的布局 － 也许把 JSON 封装到一些上下文 － 在 JSON 助手的每个方法接受第二个可选的参数：打开或关闭布局的 flag ，传递一个布尔 true 值将使布局保持打开：

class FooController extends Zend_Controller_Action
{
    public function barAction()
    {
        // Retrieve the json, keeping layouts:
        $json = $this->_helper->json->encodeJson($data, true);
    }
}

转向器(Redirector)

介绍

转向器(Redirector)助手让你使用一个转向器对象帮助程序重定向到新的URL。与_redirect()方法相比，它具有多项优势。例如能够在转向器对象中预先配置整个站点的行为，或者使用与Zend_Controller_Action::_forward()相似的gotoSimple($action, $controller, $module, $params)接口。

转向器拥有影响重定向行为的大量方法：

  • setCode() 设置重定向过程中使用的HTTP响应码。

  • setExit() 在重定向后强制执行exit()方法。默认已设定。

  • setGotoSimple()设置默认的URL，当没有提供参数给gotoSimple()方法时转向该URL。可以使用类似Zend_Controller_Action::_forward()的API：setGotoSimple($action, $controller = null, $module = null, array $params = array());

  • setGotoRoute()设置基于一个注册路由器的URL。通过传入一个键/值数组和一个路由器名，它将根据路由器的类型和定义来组织URL。

  • setGotoUrl()设置默认的URL，当没有参数传入gotoUrl()，将使用该URL。接受单个URL字符串。

  • setPrependBase()在setGotoUrl()、gotoUrl()或者gotoUrlAndExit()指定的URL前面，加入请求对象的基地址(base URL)。

  • setUseAbsoluteUri()强制转向器在重定向时使用绝对的URI。当该选项设定后，将使用$_SERVER['HTTP_HOST']、 $_SERVER['SERVER_PORT']和 $_SERVER['HTTPS']以及重定向方法指定的URL，来形成一个完整的URI。该选项目前默认关闭，将来的版本可能会默认开启。

此外，转向器中还有大量方法来执行实际的重定向。

  • gotoSimple()使用setGotoSimple()(类似_forward()的API)来构建URL并执行重定向。

  • gotoRoute()使用setGotoRoute()(路由组装route-assembly)来构建URL并执行重定向。

  • gotoUrl()使用setGotoUrl() URL字符串）来构造URL并执行重定向。

最后，你可以在任何时刻使用getRedirectUrl()确定当前的重定向URL。

基础用例

Example #5 设定选项

这个例子改变了几个选项，包括设定重定向时使用的HTTP状态码为303，重定向时不默认退出，以及定义了默认的URL供重定向使用。

class SomeController extends Zend_Controller_Action
{
    /**
     * Redirector - defined for code completion
     *
     * @var Zend_Controller_Action_Helper_Redirector
     */
    protected $_redirector = null;

    public function init()
    {
        $this->_redirector = $this->_helper->getHelper('Redirector');

        // Set the default options for the redirector
        // Since the object is registered in the helper broker, these
        // become relevant for all actions from this point forward
        $this->_redirector->setCode(303)
                          ->setExit(false)
                          ->setGotoSimple("this-action",
                                          "some-controller");
    }

    public function myAction()
    {
        /* do some stuff */

        // Redirect to a previously registered URL, and force an exit
        // to occur when done:
        $this->_redirector->redirectAndExit();
        return; // never reached
    }
}

Example #6 使用默认设定

这个例子假定使用默认设定，也就意味着任何重定向将导致立即退出。

// ALTERNATIVE EXAMPLE
class AlternativeController extends Zend_Controller_Action
{
    /**
     * Redirector - defined for code completion
     *
     * @var Zend_Controller_Action_Helper_Redirector
     */
    protected $_redirector = null;

    public function init()
    {
        $this->_redirector = $this->_helper->getHelper('Redirector');
    }

    public function myAction()
    {
        /* do some stuff */

        $this->_redirector
            ->gotoUrl('/my-controller/my-action/param1/test/param2/test2');
        return; // never reached since default is to goto and exit
    }
}

Example #7 使用goto()的_forward()API

gotoSimple()'s API 模拟了Zend_Controller_Action::_forward()。主要的不同在于它通过传入的参数构造URL，使用默认路由器的默认格式:module/:controller/:action/*。然后重定向而不是继续动作链循环。

class ForwardController extends Zend_Controller_Action
{
    /**
     * Redirector - defined for code completion
     *
     * @var Zend_Controller_Action_Helper_Redirector
     */
    protected $_redirector = null;

    public function init()
    {
        $this->_redirector = $this->_helper->getHelper('Redirector');
    }

    public function myAction()
    {
        /* do some stuff */

        // Redirect to 'my-action' of 'my-controller' in the current
        // module, using the params param1 => test and param2 => test2
        $this->_redirector->gotoSimple('my-action',
                                       'my-controller',
                                       null,
                                       array('param1' => 'test',
                                             'param2' => 'test2'
                                             )
                                       );
    }
}

Example #8 通过gotoRoute()使用路由组装(route assembly)

下面的例子使用了路由器的assemble()方法，基于传入参数的关联数组来创建URL。假定下面的路由已经注册:

$route = new Zend_Controller_Router_Route(
    'blog/:year/:month/:day/:id',
    array('controller' => 'archive',
          'module' => 'blog',
          'action' => 'view')
);
$router->addRoute('blogArchive', $route);

给定一个数组，其中年份为2006，月份为4，日期为24，id为42，据此可以组装URL/blog/2006/4/24/42。

class BlogAdminController extends Zend_Controller_Action
{
    /**
     * Redirector - defined for code completion
     *
     * @var Zend_Controller_Action_Helper_Redirector
     */
    protected $_redirector = null;

    public function init()
    {
        $this->_redirector = $this->_helper->getHelper('Redirector');
    }

    public function returnAction()
    {
        /* do some stuff */

        // Redirect to blog archive. Builds the following URL:
        // /blog/2006/4/24/42
        $this->_redirector->gotoRoute(
            array('year' => 2006,
                  'month' => 4,
                  'day' => 24,
                  'id' => 42),
            'blogArchive'
        );
    }
}

ViewRenderer

介绍

视图解析(ViewRenderer)助手为实现下列目标设计：

  • 不需要在控制器内创建视图对象实例；视图对象将在控制器内自动注册。

  • 根据当前的模块自动地设置视图脚本、助手、过滤器路径。指派当前的模块名为助手和过滤器类的类名前缀。

  • 为所有分发的控制器和动作创建全局有效的视图对象。

  • 允许开发人员为所有控制器设置默认的视图解析选项。

  • 加入无需干预自动解析试图脚本的功能。

  • 允许开发人员为视图基路径和视图脚本路径创建自己的规范。

Note: 如果手动执行_forward()、redirect、或者render时，不会发生自动解析。因为执行这些动作时，等于告诉ViewRenderer，你要自己确定输出结果。

Note: ViewRenderer助手默认启用。你可以通过前端控制器的noViewRenderer方法、设定参数($front->setParam('noViewRenderer', true))或者从助手经纪人栈(helper broker stack)中移除助手(Zend_Controller_Action_HelperBroker::removeHelper('viewRenderer'))等方式禁用该助手。
如希望在分发前端控制器前修改ViewRenderer设定，可采用下面的两种方法：

  • 创建实例并注册自己的ViewRenderer对象，然后传入到助手经纪人。

    $viewRenderer = new Zend_Controller_Action_Helper_ViewRenderer();
$viewRenderer->setView($view)
             ->setViewSuffix('php');
Zend_Controller_Action_HelperBroker::addHelper($viewRenderer);

  • 通过助手经纪人即时的初始化并/或获取ViewRenderer对象。

    $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
$viewRenderer->setView($view)
             ->setViewSuffix('php');

API

大多数使用中，只需要简单的创建 ViewRenderer对象，然后传入到动作助手经纪人。创建实例并注册的最简单方式是使用助手经纪人的getStaticHelper()方法：

Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');

动作控制器第一次实例化时，会触发ViewRenderer创建一个视图对象。动作控制器每次实例化都会调用ViewRenderer的init()方法，设定动作控制器的视图属性，并以相对于当前模块的路径为参数调用addScriptPath()方法；调用时带有以当前模块命名的类前缀参数，该参数对为该模块定义的所有助手和过滤器类都有效。(this will be called with a class prefix named after the current module, effectively namespacing all helper and filter classes you define for the module. )

每次执行postDispatch()方法，它将为当前动作执行render()方法。

例如这个类：

// A controller class, foo module:
class Foo_BarController extends Zend_Controller_Action
{
    // Render bar/index.phtml by default; no action required
    public function indexAction()
    {
    }

    // Render bar/populate.phtml with variable 'foo' set to 'bar'.
    // Since view object defined at preDispatch(), it's already available.
    public function populateAction()
    {
        $this->view->foo = 'bar';
    }
}

...

// in one of your view scripts:
$this->foo(); // call Foo_View_Helper_Foo::foo()

ViewRenderer也定义了大量的访问器用来设定和获取视图选项。

  • setView($view)可以为ViewRenderer设定视图对象。以公共类属性$view获取设定值。

  • setNeverRender($flag = true)可以全局的启用或禁用自动解析，也就是对所有控制器都有效。如果设定为true，在所有控制器器内，postDispatch()将不会自动调用render()。getNeverRender()返回当前的设定值。

  • setNoRender($flag = true) 用来启用或禁用自动解析，如果设置为true，在当前控制器内，postDispatch()不会调用render()方法。这个设定在preDispatch()每次执行时会被重置。getNoRender()返回当前的设定值。

  • setNoController($flag = true)通知render()不要再到以控制器命名的子目录中寻找视图脚本。getNoController()返回当前值。

  • setNeverController($flag = true)与setNoController($flag = true)相似，但是其在全局范围内有效——也就是说，它不会在每次分发动作时重置。getNeverController()返回当前值。

  • setScriptAction($name)用来指定解析的视图脚本。$name是脚本的名字去掉后缀(不带控制器子目录，除非noController已开启)。如果没有指定，它将寻找以请求对象中的动作命名的视图脚本。getScriptAction()返回当前值。

  • setResponseSegment($name)用来指定解析到响应对象中的哪个命名片段。如果没有指定，解析到默认片断。getResponseSegment()返回当前值。

  • initView($path, $prefix, $options)可以指定视图的基路径，为助手和过滤器脚本设置类前缀，设定ViewRenderer选项。可以传入以下任意的标志：neverRender，noRender，noController， scriptAction，和responseSegment。

  • setRender($action = null, $name = null, $noController = false)可以一次设定scriptAction、responseSegment和noController。 direct()是它的别名，使得控制器中可以方便的调用。

    // Render 'foo' instead of current action script
$this->_helper->viewRenderer('foo');

// render form.phtml to the 'html' response segment, without using a
// controller view script subdirectory:
$this->_helper->viewRenderer('form', 'html', true);

    Note: setRender() 和 direct()并不会实际解析视图脚本，而是提示postDispatch()和postDispatch()解析视图。

构造函数允许可选的传入参数视图对象和ViewRenderer选项，接受与initView()一样的标志(flags)：

$view    = new Zend_View(array('encoding' => 'UTF-8'));
$options = array('noController' => true, 'neverRender' => true);
$viewRenderer =
    new Zend_Controller_Action_Helper_ViewRenderer($view, $options);

还有几个额外的方法用来定制路径规则，供确定视图基路径来增加视图对象，确定视图脚本路径查找并解析视图脚本时使用。这些方法每个都带有下面一个或更多的占位符(placehodlers)。

  • :moduleDir 引用当前模块的基目录（常规的是模块的控制器目录的父目录）。

  • :module 引用当前的模块名。

  • :controller 引用当前的控制器名。

  • :action引用当前的模块名。

  • :suffix 引用当前的视图脚本后缀（可以通过setViewSuffix()来设置）。

控制器路径规则有关的方法:

  • setViewBasePathSpec($spec)可以改变确定加入到视图对象的基路径的路径规则。默认规则是:moduleDir/views。任何时候都可以使用getViewBasePathSpec()获取当前的规则。

  • setViewScriptPathSpec($spec)允许改变确定到达单独的视图脚本路径(去除试图脚本基路径)的路径规则。默认的路径规则是 :controller/:action.:suffix。任何时候都可以通过getViewScriptPathSpec()获取当前规则。

  • setViewScriptPathNoControllerSpec($spec)允许改变 noController有效时确定到达单独的视图脚本路径(去除试图脚本基路径)的路径规则。默认的规则是:action.:suffix，任何时候都可以通过getViewScriptPathNoControllerSpec()获取当前规则。

为在路径规范之上精心设计的控制，可以使用Zend_Filter_Inflector。深入地，视图解析器（ViewRenderer）已经使用inflector来执行路径映射。为和inflector互动 － 或者设置你自己的或者修改缺省的inflector，下面的方法可以被使用：

  • getInflector() 将获取inflector。如果在视图解析器中不存在， 它用缺省的规则创建一个。

    缺省地，它用静态规则引用和静态目标做为后缀和模块目录；这允许不同的视图解析器具备动态修改inflector能力的属性。

  • setInflector($inflector, $reference) 允许设置定制的inflector和视图解析器一起使用。如果$reference 是true，它将设置后缀和模块目录作为静态引用和目标给视图解析器 属性。

Note: 缺省查找约定（Conventions）
 视图解析器做了一些路径标准化使视图脚本查找更容易。缺省规则如下：

  • :module: 混合词和驼峰词被短横线分开，并整个串变成小写。例如："FooBarBaz" 变成 "foo-bar-baz"。

    在内部，变形器（inflector） 使用过滤器Zend_Filter_Word_CamelCaseToDash 和 Zend_Filter_StringToLower。

  • :controller: 混合词和驼峰词被短横线分开；下划线转换成目录分隔符，并且整个串变小写。例如："FooBar" becomes "foo-bar"; "FooBar_Admin" 变成 "foo-bar/admin".

    在内部，inflector 使用过滤器Zend_Filter_Word_CamelCaseToDash、Zend_Filter_Word_UnderscoreToSeparator 和 Zend_Filter_StringToLower。

  • :action: 混合词和驼峰词被短横线分开；非字母数字字符翻译成短横线，并且整个串变成小写。 例如 "fooBar" 变成 "foo-bar"； "foo-barBaz" 变成 "foo-bar-baz"。

    在内部，inflector 使用过滤器 Zend_Filter_Word_CamelCaseToDash、Zend_Filter_PregReplace 和 Zend_Filter_StringToLower。

视图解析器 API中的最后一项是关于实际确定视图脚本路径和解析视图的。包括：

  • renderScript($script, $name)允许解析指定路径的脚本，可选的命名的路径片段。(renderScript($script, $name) allows you to render a script with a path you specify, optionally to a named path segment. )使用该方法时，ViewRenderer不会自动的确定脚本名称，而是直接的向视图对象的render()传入$script参数。

    Note: 当视图已经被解析到响应对象，将会设置noRender阻止相同的脚本被多次解析。

    Note: 默认的，Zend_Controller_Action::renderScript()代理ViewRenderer的renderScript()方法。

  • getViewScript($action, $vars)基于传入的动作和/或$vars中的变量创建到视图脚本的路径。该数组中的键可以包含所有的路径指定键('moduleDir','module', 'controller', 'action', and 'suffix')。传入的任何变量都会优先使用，否则利用基于当前请求的值。

    getViewScript()根据noController标志的设定值使用viewScriptPathSpec或者viewScriptPathNoControllerSpec。

    模块、控制器以及动作中的单词定界符将后替换成短线('-')。因此，控制器名称'foo.bar'和动作'baz:bat'按照默认的路径规则将会得到视图脚本路径'foo-bar/baz-bat.phtml'。

    Note: 默认的，Zend_Controller_Action::getViewScript()代理ViewRenderer的getViewScript()方法。

  • render($action, $name, $noController)首先检查$name或 $noController参数是否传入，如果传入，则在ViewRenderer中设定相应的标志(分别是响应片段和noController)。然后传入$action参数到getViewScript()，最后传入计算的试图脚本路径到renderScript()。

    Note: 注意使用render()的边际效应：传入的响应片段名称和noController标志在视图对象中存留。此外解析结束后noRender会被设置。

    Note: 默认的，Zend_Controller_Action::render()代理 ViewRenderer的render()方法。

  • renderBySpec($action, $vars, $name)允许传入路径规则变量以确定创建的视图脚本路径。它把$action和$vars传入到getScriptPath()，将脚本路径结果和$name传入到renderScript()。

基础用法示例

Example #9 基本用法

大多数基础使用中，只需在bootstrap中使用助手经纪人简单的初始化和注册ViewRenderer 助手，然后在动作方法中设置变量。

// In your bootstrap:
Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');

...

// 'foo' module, 'bar' controller:
class Foo_BarController extends Zend_Controller_Action
{
    // Render bar/index.phtml by default; no action required
    public function indexAction()
    {
    }

    // Render bar/populate.phtml with variable 'foo' set to 'bar'.
    // Since view object defined at preDispatch(), it's already available.
    public function populateAction()
    {
        $this->view->foo = 'bar';
    }

    // Renders nothing as it forwards to another action; the new action
    // will perform any rendering
    public function bazAction()
    {
        $this->_forward('index');
    }

    // Renders nothing as it redirects to another location
    public function batAction()
    {
        $this->_redirect('/index');
    }
}

Note: 命名规则：控制器和动作名中的单词定界符
 如果控制器或者动作名称由几个单词组成，分发器要求在URL中使用特定的路径和单词定界符分隔。ViewRenderer创建路径时将控制器名称中的任何路径定界符替换成实际的路径定界符('/')，任何单词定界符替换成短线('-')。对动作/foo.bar/baz.bat的调用将分发到FooBarController.php中的FooBarController::bazBatAction()，然后解析foo-bar/baz-bat.phtml；对动作/bar_baz/baz-bat的调用将分发到Bar/BazController.php中的Bar_BazController::bazBatAction()，并解析bar/baz/baz-bat.phtml。
注意到在第二个例子中，模块依然是默认的模块，但由于路径分隔符的存在，控制器的接收到的名字为Bar_BazController，该类在文件Bar/BazController.php中。ViewRenderer模拟了控制器的目录分层。

Example #10 禁用自动解析

对于某些动作和控制器，可能希望关闭自动解析——例如，如果想发送其他类型的输出（XML,JSON等），或者更简单的不想发送任何东西。有两个选项：关闭所有的自动解析(setNeverRender())，或者仅仅关闭当前动作的自动解析(setNoRender())。

// Baz controller class, bar module:
class Bar_BazController extends Zend_Controller_Action
{
    public function fooAction()
    {
        // Don't auto render this action
        $this->_helper->viewRenderer->setNoRender();
    }
}

// Bat controller class, bar module:
class Bar_BatController extends Zend_Controller_Action
{
    public function preDispatch()
    {
        // Never auto render this controller's actions
        $this->_helper->viewRenderer->setNoRender();
    }
}

Note: 大多数情况下，全局的关闭自动解析(setNeverRender())没有意义，因为这样ViewRenderer做的唯一件事只是自动设置了视图对象。

Example #11 选择另外的视图脚本

有些情况下需要解析另一个脚本而非以动作命名的脚本。例如，如果你有一个控制器包含增加和编辑两个动作，它们可能都显示相同的'form'视图，尽管拥有不同的值集合(value set)。只需要使用setScriptAction()或者setRender()简单的改变脚本的名称，或者以成员方法的形式调用助手，它将调用setRender()。

// Bar controller class, foo module:
class Foo_BarController extends Zend_Controller_Action
{
    public function addAction()
    {
        // Render 'bar/form.phtml' instead of 'bar/add.phtml'
        $this->_helper->viewRenderer('form');
    }

    public function editAction()
    {
        // Render 'bar/form.phtml' instead of 'bar/edit.phtml'
        $this->_helper->viewRenderer->setScriptAction('form');
    }

    public function processAction()
    {
        // do some validation...
        if (!$valid) {
            // Render 'bar/form.phtml' instead of 'bar/process.phtml'
            $this->_helper->viewRenderer->setRender('form');
            return;
        }

        // otherwise continue processing...
    }

}

Example #12 修改注册的视图Modifying the registered view

如果需要修改视图对象怎么办——例如改变助手路径或者编码？可以在控制器中修改视图对象设定，或者从ViewRenderer中抓取视图对象；两种方式引用的是同一个对象。

// Bar controller class, foo module:
class Foo_BarController extends Zend_Controller_Action
{
    public function preDispatch()
    {
        // change view encoding
        $this->view->setEncoding('UTF-8');
    }

    public function bazAction()
    {
        // Get view object and set escape callback to 'htmlspecialchars'
        $view = $this->_helper->viewRenderer->view;
        $view->setEscape('htmlspecialchars');
    }
}

高级用法示例

Example #13 修改路径规则

有些情况下，默认的路径规则可能并不适合站点的需要。比如，希望拥有一个单独的模板树供设计人员访问（例如，如果你使用» Smarty，这是很典型的情形）。这种情况下，你可能想硬编码视图的基路径规则，为动作视图脚本路径自身创建一套规则。

假定视图的基路径(base path)为'/opt/vendor/templates',希望通过':moduleDir/:controller/:action.:suffix'引用视图脚本；如果设定了noController标志，想在顶级而不是在子目录中解析(':action.:suffix')。最终希望使用'tpl'作为视图脚本文件的后缀。

/**
 * In your bootstrap:
 */

// Different view implementation
$view = new ZF_Smarty();

$viewRenderer = new Zend_Controller_Action_Helper_ViewRenderer($view);
$viewRenderer->setViewBasePathSpec('/opt/vendor/templates')
             ->setViewScriptPathSpec(':module/:controller/:action.:suffix')
             ->setViewScriptPathNoControllerSpec(':action.:suffix')
             ->setViewSuffix('tpl');
Zend_Controller_Action_HelperBroker::addHelper($viewRenderer);

Example #14 一个动作中解析多个视图脚本

有时可能需要在一个动作中解析多个视图脚本。这个非常简单，多次调用render()就行了：

class SearchController extends Zend_Controller_Action
{
    public function resultsAction()
    {
        // Assume $this->model is the current model
        $this->view->results =
            $this->model->find($this->_getParam('query', '');

        // render() by default proxies to the ViewRenderer
        // Render first the search form and then the results
        $this->render('form');
        $this->render('results');
    }

    public function formAction()
    {
        // do nothing; ViewRenderer autorenders the view script
    }
}

编写自己的助手

动作助手继承抽象类Zend_Controller_Action_Helper_Abstract，该类提供了助手经纪人要求的基本接口和功能，包含下列方法：

  • setActionController() 用来设置当前的动作控制器。

  • init()，该方法在实例化时由助手经纪人触发，可用来触发助手的初始化过程；动作链中多个控制器使用相同的助手时，如要恢复状态时将十分有用。

  • preDispatch()分发动作之前触发。

  • postDispatch()分发过程结束时触发——即使preDispatch()插件已经跳过了该动作。清理时大量使用。

  • getRequest() 获取当前的请求对象。

  • getResponse() 获取当前的响应对象。

  • getName() 获取助手名。获取了下划线后面的类名部分，没有下划线则获取类的全名。例如，如果类名为Zend_Controller_Action_Helper_Redirector，他将返回 Redirector，如果类名为FooMessage，将会返回全名。

助手类中还可以包含一个direct()方法，如果定义了该方法，就可以将助手视作助手经纪人的一个方法，以便简单的、一次性的使用助手。例如redirector 定义direct() 作为goto()的别名,就可以这样使用：

// Redirect to /blog/view/item/id/42
$this->_helper->redirector('item', 'view', 'blog', array('id' => 42));

在内部，助手经纪人的__call()方法先寻找名叫redirector的助手，然后检查该助手的direct方法是否定义，然后使用所提供的参数来调用该方法。

如果创建了自己的助手，可以按照前面章节所述的提供相应的访问方法。

动作控制器
Zend_Controller
Zend Framework手册 中文版
响应对象
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Controller
  • Zend_Controller 快速入门
  • Zend_Controller 基础
  • 前端控制器
  • 请求对象
  • 标准路由器
  • 分发器
  • 动作控制器
  • 动作助手
  • 响应对象
  • 插件
  • 使用传统的模块目录结构
  • MVC 异常


响应对象 - Zend Framework Manual

动作助手
Zend_Controller
Zend Framework手册 中文版
插件

响应对象

用法

响应对象逻辑上是请求对象的搭档.目的在于收集消息体和/或消息头，因而可能返回大批的结果。另外前端控制器可能传递任何异常到响应对象，允许开发人员优美的处理异常。可以通过设置 Zend_Controller_Front::throwExceptions(true)覆盖这项功能：

$front->throwExceptions(true);

如果要发送响应输出包括消息头，使用sendResponse()。

$response->sendResponse();

Note: 默认地，前端控制器完成分发请求后调用sendResponse()；一般地，你不需要调用它。但是，如果你想处理响应或者用它来测试你可以使用Zend_Controller_Front::returnResponse(true)设置returnResponse 标志覆盖默认行为：

$front->returnResponse(true);
$response = $front->dispatch();

// do some more processing, such as logging...
// and then send the output:
$response->sendResponse();

开发人员可以在动作控制器中使用响应对象。把结果写进响应对象，而不是直接渲染输出和发送消息头：

// Within an action controller action:
// Set a header
$this->getResponse()
    ->setHeader('Content-Type', 'text/html')
    ->appendBody($content);

这样做，可以在显示内容之前，将所有消息头一次发送。

Note: 如果使用动作控制器的 视图集成(view integration)，你不需要在相应对象中设置渲染的视图脚本，因为Zend_Controller_Action::render() 默认完成了这些。

如果程序中发生了异常，检查响应对象的isException() 标志，使用getException()获取异常。此外，可以创建定制的响应对象重定向到错误页面，记录异常消息，漂亮的格式化异常消息等。

在前端控制器执行dispatch()后可以获得响应对象，或者请求前端控制器返回响应对象代替渲染输出。

// retrieve post-dispatch:
$front->dispatch();
$response = $front->getResponse();
if ($response->isException()) {
    // log, mail, etc...
}

// Or, have the front controller dispatch() process return it
$front->returnResponse(true);
$response = $front->dispatch();

// do some processing...

// finally, echo the response
$response->sendResponse();

默认地，异常消息是不显示的。可以通过调用renderExceptions()覆盖默认设置。或者启用前端控制器的throwExceptions():

$response->renderExceptions(true);
$front->dispatch($request, $response);

// or:
$front->returnResponse(true);
$response = $front->dispatch();
$response->renderExceptions();
$response->sendResponse();

// or:
$front->throwExceptions(true);
$front->dispatch();

处理消息头

如上文所述，响应对象的一项重要职责是收集和发出HTTP响应消息头，相应地存在大量的方法:

  • canSendHeaders() 用来判别消息头是否已发送，该方法带有一个可选的标志指示消息头已发出时是否抛出异常。可以通过设置headersSentThrowsException 属性为false来覆盖默认设置。

  • setHeader($name, $value, $replace = false)用来设置单独的消息头。默认的不会替换已经存在的同名消息头，但可以设置$replace 为true强制替换.

    设置消息头前，该方法先检查canSendHeaders()看操作是否允许，并请求抛出异常。

  • setRedirect($url, $code = 302) 设置HTTP定位消息头准备重定向，如果提供HTTP状态码，重定向将会使用该状态码。

    其内部调用setHeader()并使$replace 标志呈打开状态确保只发送一次定位消息头。

  • getHeaders() 返回一个消息头数组，每个元素都是一个带有'name'和'value'键的数组。

  • clearHeaders() 清除所有注册的键值消息头。

  • setRawHeader() 设置没有键值对的原始消息头，比如HTTP状态消息头。

  • getRawHeaders() 返回所有注册的原始消息头。

  • clearRawHeaders()清除所有的原始消息头。

  • clearAllHeaders() 清除所有的消息头，包括原始消息头和键值消息头。

除了上述方法，还有获取和设置当前请求HTTP响应码的访问器， setHttpResponseCode() 和 getHttpResponseCode().

命名片段

相应对象支持“命名片段”。允许你将消息体分割成不同的片段，并呈一定顺序排列。因此输出的是以特定次序返回的。在其内部，主体内容被存储为一个数组，大量的访问器方法可以用来指示数组内位置和名称。

举例来说，你可以使用preDispatch() 钩子来向响应对象中加入页头，然后在动作控制器中加入主体内容，最后在postDispatch()钩子中加入页脚。

// Assume that this plugin class is registered with the front controller
class MyPlugin extends Zend_Controller_Plugin_Abstract
{
    public function preDispatch(Zend_Controller_Request_Abstract $request)
    {
        $response = $this->getResponse();
        $view = new Zend_View();
        $view->setBasePath('../views/scripts');

        $response->prepend('header', $view->render('header.phtml'));
    }

    public function postDispatch(Zend_Controller_Request_Abstract $request)
    {
        $response = $this->getResponse();
        $view = new Zend_View();
        $view->setBasePath('../views/scripts');

        $response->append('footer', $view->render('footer.phtml'));
    }
}

// a sample action controller
class MyController extends Zend_Controller_Action
{
    public function fooAction()
    {
        $this->render();
    }
}

上面的例子中，调用/my/foo会使得最终响应对象中的内容呈现下面的结构：

array(
    'header'  => ..., // header content
    'default' => ..., // body content from MyController::fooAction()
    'footer'  => ...  // footer content
);

渲染响应时，会按照数组中元素顺序来渲染。

大量的方法可以用来处理命名片段：

  • setBody() 和 appendBody() 都允许传入一个$name参数，指示一个命名片段。如果提供了这个参数，将会覆盖指定的命名片段，如果该片段不存在就创建一个。如果没有传入$name参数到setBody()，将会重置整个主体内容。如果没有传入$name参数到appendBody()，内容被附加到'default'命名片段。

  • prepend($name, $content) 将创建一个$name命名片段并放置在数组的开始位置。如果该片段存在，将首先移除。

  • append($name, $content) 将创建一个$name命名片段，并放置在数组的结尾位置。 如果该片段存在，将首先移除。

  • insert($name, $content, $parent = null, $before = false) 将创建一个$name命名片段。如果提供$parent参数，新的片段视$before的值决定放置在 $parent的前面或者后面。如果该片段存在，将首先移除。

  • clearBody($name = null) 如果$name参数提供，将删除该片段，否则删除全部。

  • getBody($spec = false) 如果$spec参数为一个片段名称，将可以获取到该字段。若$spec参数为false，将返回字符串格式的命名片段顺序链。如果$spec参数为true,返回主体内容数组。

在响应对象中测试异常

如上文所述，默认的，分发过程中的异常发生会在响应对象中注册。异常会注册在一个堆中，允许你抛出所有异常--程序异常，分发异常，插件异常等。如果你要检查或者记录特定的异常，你可能想要使用响应对象的异常API：

  • setException(Exception $e) 注册一个异常。

  • isException() 判断该异常是否注册。

  • getException() 返回整个异常堆。

  • hasExceptionOfType($type) 判断特定类的异常是否在堆中。

  • hasExceptionOfMessage($message) 判断带有指定消息的异常是否在堆中。

  • hasExceptionOfCode($code) 判断带有指定代码的异常是否在堆中。

  • getExceptionByType($type) 获取堆中特定类的所有异常。如果没有则返回false，否则返回数组。

  • getExceptionByMessage($message) 获取堆中带有特定消息的所有异常。如果没有则返回false，否则返回数组。

  • getExceptionByCode($code) 获取堆中带有特定编码的所有异常。如果没有则返回false，否则返回数组。

  • renderExceptions($flag) 设置标志指示当发送响应时是否发送其中的异常。

子类化响应对象

响应对象的目的首先在于从大量的动作和插件中收集消息头和内容，然后返回到客户端；其次，响应对象也收集发生的任何异常，以处理或者返回这些异常，再或者对终端用户隐藏它们。

响应的基类是Zend_Controller_Response_Abstract，创建的任何子类必须继承这个类或它的衍生类。前面的章节中已经列出了大量可用的方法。

子类化响应对象的原因包括基于请求环境修改返回的内容的输出方式（例如：在CLI和PHP-GTK请求中不发送消息头）增加返回存储在命名片段中内容的最终视图的功能等等。

动作助手
Zend_Controller
Zend Framework手册 中文版
插件
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Controller
  • Zend_Controller 快速入门
  • Zend_Controller 基础
  • 前端控制器
  • 请求对象
  • 标准路由器
  • 分发器
  • 动作控制器
  • 动作助手
  • 响应对象
  • 插件
  • 使用传统的模块目录结构
  • MVC 异常


插件 - Zend Framework Manual

响应对象
Zend_Controller
Zend Framework手册 中文版
使用传统的模块目录结构

插件

简介

控制器（Controller）结构包含一个可以在控制器周期内确定事件发生时调用用户代码的插件系统。 前端控制器（Front controller）使用插件 broker 作为用户插件注册，同时插件 broker 确保前端控制器中注册的每个插件都在事件发生时调用相应的事件方法。

事件方法定义在虚类 Zend_Controller_Plugin_Abstract，用户插件应当从这个类继承：

  • routeStartup() 在 Zend_Controller_Front 向注册的 路由器 发送请求前被调用。

  • routeShutdown() 在 路由器 完成请求的路由后被调用。

  • dispatchLoopStartup() 在 Zend_Controller_Front 进入其分发循环（dispatch loop）前被调用。

  • preDispatch() 在动作由 分发器 分发前被调用。该回调方法允许代理或者过滤行为。通过修改请求和重设分发标志位（利用 Zend_Controller_Request_Abstract::setDispatched(false) ）当前动作可以跳过或者被替换。

  • postDispatch() 在动作由 分发器 分发后被调用。该回调方法允许代理或者过滤行为。通过修改请求和重设分发标志位（利用 Zend_Controller_Request_Abstract::setDispatched(false) ）可以指定新动作进行分发。

  • dispatchLoopShutdown() 在 Zend_Controller_Front 推出其分发循环后调用。

编写插件

只需要包含并扩展抽象类 Zend_Controller_Plugin_Abstract 即可编写插件类。

class MyPlugin extends Zend_Controller_Plugin_Abstract
{
    // ...
}

Zend_Controller_Plugin_Abstract 的全部方法都不是抽象的， 这意味着插件类并不是一定要去实现前面列出的每一个事件方法。 插件的开发者只要实现需要用到的方法即可。

Zend_Controller_Plugin_Abstract 也可以通过调用 getRequest() 和 getResponse() 方法从控制器中分别获取 request 对象和 response 对象.

使用插件

可以使用 Zend_Controller_Front::registerPlugin() 在任何时候注册插件类。 下面的代码片段说明了如何在控制器链条中使用插件。

class MyPlugin extends Zend_Controller_Plugin_Abstract
{
    public function routeStartup(Zend_Controller_Request_Abstract $request)
    {
        $this->getResponse()->appendBody("<p>routeStartup() called</p>\n");
    }

    public function routeShutdown(Zend_Controller_Request_Abstract $request)
    {
        $this->getResponse()->appendBody("<p>routeShutdown() called</p>\n");
    }

    public function dispatchLoopStartup(Zend_Controller_Request_Abstract $request)
    {
        $this->getResponse()->appendBody("<p>dispatchLoopStartup() called</p>\n");
    }

    public function preDispatch(Zend_Controller_Request_Abstract $request)
    {
        $this->getResponse()->appendBody("<p>preDispatch() called</p>\n");
    }

    public function postDispatch(Zend_Controller_Request_Abstract $request)
    {
        $this->getResponse()->appendBody("<p>postDispatch() called</p>\n");
    }

    public function dispatchLoopShutdown()
    {
        $this->getResponse()->appendBody("<p>dispatchLoopShutdown() called</p>\n");
    }
}

$front = Zend_Controller_Front::getInstance();
$front->setControllerDirectory('/path/to/controllers')
      ->setRouter(new Zend_Controller_Router_Rewrite())
      ->registerPlugin(new MyPlugin());
$front->dispatch();

假设没有动作产生任何输出，而只有一个动作被调用，前面演示的插件仍然会产生下面的输出：

<p>routeStartup() called</p>
<p>routeShutdown() called</p>
<p>dispatchLoopStartup() called</p>
<p>preDispatch() called</p>
<p>postDispatch() called</p>
<p>dispatchLoopShutdown() called</p>

Note: 插件可以在前端控制器（Front controller）执行的任何时候被被注册， 如果一个事件在注册时已经完成，则这个事件对应的事件方法不会被触发。

获取和控制插件

有时，可能需要取消注册或者获取一个插件。下面列出的前端控制器中的方法可以实现这个功能：

  • getPlugin($class) 允许获取指定类名的一个插件。 如果没有插件匹配，将返回 false。如果有多个指定类的插件被注册，则返回一个数组。

  • getPlugins() 返回全部插件。

  • unregisterPlugin($plugin) 允许从插件列表中移除一个插件。 传递一个插件件对象，或者需要移除的插件的类名。如果传递类名，任何该类的插件都将被移除。

包含在标准发行包中的插件

Zend Framework 在其标准发行包中包含错误处理插件。

动作堆栈

动作堆栈插件可以管理一个请求堆栈，其操作象postDispatch插件。如果一个转发（例如，对另一个动作的调用）在当前请求对象中已经检测到，它不做任何事情。然而，如果没有检测到，它就检查堆栈并把最上面的一个取出，然后转发给由那个请求指定的动作。堆栈按照LIFO（后进先出）顺序处理。

你可以在任何时候用 Zend_Controller_Front::getPlugin('Zend_Controller_Plugin_ActionStack')从前端控制器获取插件。一旦你有插件对象，有很多机制你可以用来操作。

  • getRegistry() 和 setRegistry()。在内部， 动作堆栈 使用一个Zend_Registry 实例来存储堆栈。你可以用不同的注册表实例来代替或在这些访问器里获取。

  • getRegistryKey() 和 setRegistryKey()。当弹出堆栈时，这些可以用来识别使用哪个注册表键。缺省地值是'Zend_Controller_Plugin_ActionStack'。

  • getStack() 允许你全面地获取动作堆栈。

  • pushStack() 和 popStack() 分别允许你弹出和压栈。pushStack() 接受请求对象。

一个附加的方法，forward()，准备一个请求对象，并在前端控制器设置当前请求状态给提供的请求对象的状态，使它不可派遣（强制另一个派遣循环迭代）。

Zend_Controller_Plugin_ErrorHandler

Zend_Controller_Plugin_ErrorHandler提供了一个活动的插件，用来处理从程序抛出的异常，包括那些从缺控制器或动作的来的结果；它是一个列在MVC Exceptions section里的方法的一个替代。

插件的基本目标是：

  • 监视由于缺失控制器或动作方法而产生的异常

  • 监视动作控制器里产生的异常

换句话说，ErrorHandler 插件设计用来处理HTTP 404 类型的错误（找不到页面）和 500 类型错误（内部错误）。它不打算抓取有其它插件或路由产生的异常。

缺省地，在缺省模块中，Zend_Controller_Plugin_ErrorHandler将转发给ErrorController::errorAction()。你可以通过使用在插件中不同的访问器给它们设置替代的值：

  • setErrorHandlerModule() 设置控制器模块来使用。

  • setErrorHandlerController() 设置控制器来用。

  • setErrorHandlerAction() 设置控制器动作来用。

  • setErrorHandler()接受联合数组，它可以包含任何键，如'module'、 'controller' 或 'action'，以及要给它们设置的合适的值。

另外，你可以传递一个可选的联合数组给可以代理setErrorHandler()的构造函数。

Zend_Controller_Plugin_ErrorHandler注册一个postDispatch()钩子和检查注册在响应对象里的异常。如果发现有异常，它试图转发给注册的错误处理器（handler）动作。

如果在派遣错误处理器时发生异常，这插件将告诉前端控制器抛出异常，并重新抛出和带响应对象注册的最后一个异常。

使用 ErrorHandler 作为一个 404 处理器（handler）

因为ErrorHandler插件不仅抓取程序错误，而且也抓取在控制器链里的由于缺失控制器类和/或动作方法而产生的错误，它可以用作一个404处理器。这样做，需要让错误控制器检查异常类型。

异常的抓取被记录在一个对象里，这个对象注册在请求里。使用Zend_Controller_Action::_getParam('error_handler')来读取它：

class ErrorController extends Zend_Controller_Action
{
    public function errorAction()
    {
        $errors = $this->_getParam('error_handler');
    }
}

一旦有错误对象，可通过$errors->type来获得类型。它将是下面其中之一：

  • Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER，指示控制器没有被发现。

  • Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION，指示请求动作没有被发现。

  • Zend_Controller_Plugin_ErrorHandler::EXCEPTION_OTHER，指示其它异常。

然后可以测试头两个类型中的任意一个，并且，如果这样，显示一个404页面：

class ErrorController extends Zend_Controller_Action
{
    public function errorAction()
    {
        $errors = $this->_getParam('error_handler');

        switch ($errors->type) {
            case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER:
            case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION:
                // 404 error -- controller or action not found
                $this->getResponse()
                     ->setRawHeader('HTTP/1.1 404 Not Found');

                // ... get some output to display...
                break;
            default:
                // application error; display error page, but don't
                // change status code
                break;
        }
    }
}

最后，你可以读取异常，这个异常由错误管理器通过抓取error_handler对象的exception属性来触发的：

public function errorAction()
{
        $errors = $this->_getParam('error_handler');

        switch ($errors->type) {
            case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER:
            case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION:
                // 404 error -- controller or action not found
                $this->getResponse()
                      ->setRawHeader('HTTP/1.1 404 Not Found');

                // ... get some output to display...
                break;
            default:
                // application error; display error page, but don't change
                // status code

                // ...

                // Log the exception:
                $exception = $errors->exception;
                $log = new Zend_Log(
                    new Zend_Log_Writer_Stream(
                        '/tmp/applicationException.log'
                    )
                );
                $log->debug($exception->getMessage() . "\n" .
                            $exception->getTraceAsString());
                break;
        }
}

处理以前呈现的(rendered)输出

如果你在一个请求里派遣多个动作，或者你的动作对render()做多次调用，很可能响应对象已经有存储在它里面的内容。这可以导致呈显期望的内容和错误的内容的混合体。

如果你希望呈现错误内嵌到这样的页面，不需要修改。如果你不希望呈现这样的内容，你应该在呈现任何视图之前清除响应体：

$this->getResponse()->clearBody();

插件用法示例

Example #1 Standard usage

$front = Zend_Controller_Front::getInstance();
$front->registerPlugin(new Zend_Controller_Plugin_ErrorHandler());

Example #2 Setting a different error handler

$front = Zend_Controller_Front::getInstance();
$front->registerPlugin(new Zend_Controller_Plugin_ErrorHandler(array(
    'module'     => 'mystuff',
    'controller' => 'static',
    'action'     => 'error'
)));

Example #3 Using accessors

$plugin = new Zend_Controller_Plugin_ErrorHandler();
$plugin->setErrorHandlerModule('mystuff')
       ->setErrorHandlerController('static')
       ->setErrorHandlerAction('error');

$front = Zend_Controller_Front::getInstance();
$front->registerPlugin($plugin);

错误控制器示例

为了使用错误处理器插件，你需要错误控制器。下面是个简单的例子。

class ErrorController extends Zend_Controller_Action
{
    public function errorAction()
    {
        $errors = $this->_getParam('error_handler');

        switch ($errors->type) {
            case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER:
            case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION:
                // 404 error -- controller or action not found
                $this->getResponse()->setRawHeader('HTTP/1.1 404 Not Found');

                $content =<<<EOH
<h1>Error!</h1>
<p>The page you requested was not found.</p>
EOH;
                break;
            default:
                // application error
                $content =<<<EOH
<h1>Error!</h1>
<p>An unexpected error occurred. Please try again later.</p>
EOH;
                break;
        }

        // Clear previous content
        $this->getResponse()->clearBody();

        $this->view->content = $content;
    }
}
响应对象
Zend_Controller
Zend Framework手册 中文版
使用传统的模块目录结构
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Controller
  • Zend_Controller 快速入门
  • Zend_Controller 基础
  • 前端控制器
  • 请求对象
  • 标准路由器
  • 分发器
  • 动作控制器
  • 动作助手
  • 响应对象
  • 插件
  • 使用传统的模块目录结构
  • MVC 异常


使用传统的模块目录结构 - Zend Framework Manual

插件
Zend_Controller
Zend Framework手册 中文版
MVC 异常

使用传统的模块目录结构

简介

传统的模块目录结构允许你把不同的MVC应用程序分离成为独立的单元，并和不同的前端控制器配合再使用。示例一下这样的目录结构：

docroot/
    index.php
application/
    default/
        controllers/
            IndexController.php
            FooController.php
        models/
        views/
            scripts/
                index/
                foo/
            helpers/
            filters/
    blog/
        controllers/
            IndexController.php
        models/
        views/
            scripts/
                index/
            helpers/
            filters/
    news/
        controllers/
            IndexController.php
            ListController.php
        models/
        views/
        views/
            scripts/
                index/
                list/
            helpers/
            filters/

在这个范例中，模块名作为它所包含的控制器的前缀。上面的例子包含三个模块控制器：'Blog_IndexController' 'News_IndexController' 和'News_ListController'。也定义了两个全局控制器：'IndexController' 和 'FooController'。它们都将不需要命名空间前缀。这个目录结构在本章中用作为例子。

Note: 在缺省模块中不用命名空间前缀
 注意在缺省模块中，控制器不需要一个命名空间前缀。这样，在上例中，在缺省模块中的控制器不需要'Default_'这样的前缀－－根据它们的基本控制器名'IndexController' 和 'FooController'被简单地派遣。然而，命名空间前缀被用于所有其它模块。

那么，你怎样用Zend Framework MVC组件来实现这样的目录结构？

指定模块控制器目录

利用模块的第一步是来修改你如何在前端控制器指定控制器目录列表。在基本的MVC系列，传递数组或字符串给setControllerDirectory()，或者传递路径给addControllerDirectory()。当使用模块，你需要稍微修改对这些方法的调用。

用setControllerDirectory()，你将需要传递一个关联数组和指定‘模块名/目录路径’的‘键/值’对。特殊的键default 将被用作全局控制器（不需要模块命名空间）。所有条目应该包含指向一个单个路径的字符串键，并且default键必须出现。例如：

$front->setControllerDirectory(array(
    'default' => '/path/to/application/controllers',
    'blog'    => '/path/to/application/blog/controllers'
));

addControllerDirectory()将带有可选的第二个参数。当使用模块，传递模块名作为第二个参数；如果没有指定，路径将被加到default命名空间。例如：

$front->addControllerDirectory('/path/to/application/news/controllers',
                               'news');

把最好的保留到最后，指定模块的最容易的方法是整体来做，把所有模块放到一个通用的目录并使用相同的结构。这可以用addModuleDirectory()来完成：

/**
 * Assuming the following directory structure:
 * application/
 *     modules/
 *         default/
 *             controllers/
 *         foo/
 *             controllers/
 *         bar/
 *             controllers/
 */
$front->addModuleDirectory('/path/to/application/modules');

上面的例子将定义default、foo 和 bar模块，每个都分别指向它们的模块的controllers子目录。

你可以在模块中通过setModuleControllerDirectoryName()来定制模块子目录：

/**
 * Change the controllers subdirectory to be 'con'
 * application/
 *     modules/
 *         default/
 *             con/
 *         foo/
 *             con/
 *         bar/
 *             con/
 */
$front->setModuleControllerDirectoryName('con');
$front->addModuleDirectory('/path/to/application/modules');

Note: 你可以通过传递一个空值给setModuleControllerDirectoryName()来指定在你的模块中没有控制器子目录。

Routing to modules

在Zend_Controller_Router_Rewrite中缺省的路由是一个Zend_Controller_Router_Route_Module类型的对象。这个路由使用下面路由计划之一：

  • :module/:controller/:action/*

  • :controller/:action/*

换句话说，它将自己或通过先前的模块来匹配控制器和动作。匹配规则指定一个模块将只匹配在传递给前端控制器和派遣器的控制器目录数组中存在同名的键。

模块或全局缺省控制器

在缺省的路由器中，如果在URL中没有指定控制器，缺省控制器就被使用（IndexController，除非另外要求）。对于模块控制器，如果一个模块被指定但没有控制器，派遣器首先寻找在这个模块路径中的缺省控制器，然后回到在'default'、全局、命名空间中发现的缺省控制器。

如果你总愿意缺省到全局命名空间，在前端控制器中设置useDefaultControllerAlways 参数：

$front->setParam('useDefaultControllerAlways', true);
插件
Zend_Controller
Zend Framework手册 中文版
MVC 异常
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Controller
  • Zend_Controller 快速入门
  • Zend_Controller 基础
  • 前端控制器
  • 请求对象
  • 标准路由器
  • 分发器
  • 动作控制器
  • 动作助手
  • 响应对象
  • 插件
  • 使用传统的模块目录结构
  • MVC 异常


MVC 异常 - Zend Framework Manual

使用传统的模块目录结构
Zend_Controller
Zend Framework手册 中文版
Zend_Currency

MVC 异常

介绍

Zend Framework 中的MVC元件利用了一个前端控制器，这意味着到一个站点的所有请求都将通过单一入口。因此，所有的异常最终将起泡到前端控制器，开发人员可在一个位置处理这些异常。

但是，异常消息以及回溯信息可能含有敏感的系统信息，比如SQL语句，文件位置等等。为了保护站点，Zend_Controller_Front 默认将捕捉所有异常并注册到响应对象，响应对象默认不会显示异常消息。

如何处理异常?

MVC元件已经建立了几种机制来处理异常。

  • 默认地，错误处理器插件（error handler plugin） 将会被注册并激活。这个插件可以处理：

    • 控制器或动作缺失导致的异常

    • 动作控制器中发生的异常

    它作为一个postDispatch()插件，检查分发器、动作控制器或者其他的异常是否发生。如果发生异常，它将转向一个错误处理控制器。

    该处理器会涵盖大多数异常情况，并能够优美的处理控制器或者动作缺失异常。

  • Zend_Controller_Front::throwExceptions()

    通过向该方法传入一个true值，可以通知前端控制器，由开发人员来处理异常，而不是让响应对象收集或者使用错误处理器插件。例如：

    $front->throwExceptions(true);
try	{
    $front->dispatch();
} catch	(Exception $e) {
    // handle exceptions yourself
}

    这是向前端控制器中加入定制处理所有可能异常的最简单方式。

  • Zend_Controller_Response_Abstract::renderExceptions()

    通过向该方法中传入一个true值，可以让响应对象渲染（render）异常消息，当渲染响应对象时追踪异常（backtrace）。这种情况下，将会显示程序中引发的所有异常。推荐只在非生产（non-production）环境中使用。

  • Zend_Controller_Front::returnResponse() 和 Zend_Controller_Response_Abstract::isException().

    向Zend_Controller_Front::returnResponse()传入一个true值, Zend_Controller_Front::dispatch() 将不渲染响应对象，而是将其返回。获得响应对象后，可通过isException()测试是否捕捉到异常，然后通过getException()获取异常。例如：

    $front->returnResponse(true);
$response =	$front->dispatch();
if ($response->isException()) {
    $exceptions	= $response->getException();
    // handle exceptions ...
} else {
    $response->sendHeaders();
    $response->outputBody();
}

    这种方式相对于Zend_Controller_Front::throwExceptions()的主要优点在于，可以在异常处理后有条件的渲染响应对象。不像错误处理器插件，该方法能够捕捉到控制器链中的任何异常。

可能遭遇的MVC异常

各种MVC元件--请求，路由器，分发器，动作控制器，响应对象--在同一事件中可能每一个都会抛出异常。一些异常可能根据情况被忽略，其他的则提示开发人员考虑程序的结构。

比如：

  • 如果请求一个无效的控制器，Zend_Controller_Dispatcher::dispatch() 默认会抛出一个异常。推荐采用两种方式来处理。

    • 设置useDefaultControllerAlways参数。

      在前端控制器或者分发器中，加入下列代码：

      $front->setParam('useDefaultControllerAlways', true);

// or

$dispatcher->setParam('useDefaultControllerAlways',	true);

      设置了这个标志，分发器将调用默认的控制器和动作，而不是抛出异常。该方法的缺点是用户访问站点时的URL拼写错误，依然会被解析并显示默认页，这将严重破坏搜索引擎的优化。

    • dispatch()抛出的异常是一个包含文本'Invalid controller specified'的Zend_Controller_Dispatcher_Exception。使用前一节描述的方法捕捉异常，然后重定向到一个一般性的错误页面或者主页。

  • 如果由于动作不存在而无法分发，Zend_Controller_Action::__call() 将会抛出一个Zend_Controller_Action_Exception异常。很有可能，像这些例子一样，你会在控制器中调用默认的动作。这些方法包括：

    • 子类化Zend_Controller_Action并重写__call() 方法。例如：

      class My_Controller_Action extends Zend_Controller_Action
{
    public function	__call($method,	$args)
    {
        if ('Action' ==	substr($method,	-6)) {
            $controller	= $this->getRequest()->getControllerName();
            $url = '/' . $controller . '/index';
            return $this->_redirect($url);
        }

        throw new Exception('Invalid method');
    }
}

      上面的例子拦截所有未定义的动作调用，并重定向到控制器中的默认动作。

    • 子类化Zend_Controller_Dispatcher 并重写getAction() 方法来验证动作的存在。例如：

      class My_Controller_Dispatcher extends Zend_Controller_Dispatcher
{
    public function	getAction($request)
    {
        $action	= $request->getActionName();
        if (empty($action))	{
            $action	= $this->getDefaultAction();
            $request->setActionName($action);
            $action	= $this->formatActionName($action);
        } else {
            $controller	= $this->getController();
            $action		= $this->formatActionName($action);
            if (!method_exists($controller,	$action)) {
                $action	= $this->getDefaultAction();
                $request->setActionName($action);
                $action	= $this->formatActionName($action);
            }
        }

        return $action;
    }
}

      上面的代码检查请求的动作在控制类中是否存在，不存在的话，将动作重置为默认动作。

      这个方法好在你可以在最终分发前透明的改变动作。然而，同样意味着URL中的拼写错误会导致不正确的分发，这对搜索引擎的优化很不利。

    • 使用Zend_Controller_Action::preDispatch()或者Zend_Controller_Plugin_Abstract::preDispatch()来识别无效的动作。

      通过子类化Zend_Controller_Action并修改preDispatch()方法，你可以修改所有的控制器转向另一个动作，或者在实际分发动作之前重定向。代码看起来与上面重写__call()方法类似。

      也可以选择在一个全局插件中检查该信息。其优点在于保持动作控制器的独立性；如果程序由大量的动作控制器组成，并且不是所有的动作控制器都从同一类继承，这种方法可以统一的控制各个类。

      例如：

      class My_Controller_PreDispatchPlugin extends Zend_Controller_Plugin_Abstract
{
    public function	preDispatch(Zend_Controller_Request_Abstract $request)
    {
        $dispatcher	=
            Zend_Controller_Front::getInstance()->getDispatcher();
        $controller	= $dispatcher->getController($request);
        if (!$controller) {
            $controller	=
                $dispatcher->getDefaultControllerName($request);
        }
        $action		= $dispatcher->getAction($request);

        if (!method_exists($controller,	$action)) {
            $defaultAction = $dispatcher->getDefaultAction();
            $controllerName	= $request->getControllerName();
            $response =
                Zend_Controller_Front::getInstance()->getResponse();
            $response->setRedirect('/' . $controllerName .
                                   '/' . $defaultAction);
            $response->sendHeaders();
            exit;
        }
    }
}

      这个例子中，先检查请求的动作在控制器中是否有效。如果无效，重定向到控制器默认的动作，并立即退出脚本的执行。

使用传统的模块目录结构
Zend_Controller
Zend Framework手册 中文版
Zend_Currency
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Controller
  • Zend_Controller 快速入门
  • Zend_Controller 基础
  • 前端控制器
  • 请求对象
  • 标准路由器
  • 分发器
  • 动作控制器
  • 动作助手
  • 响应对象
  • 插件
  • 使用传统的模块目录结构
  • MVC 异常


Zend_Currency - Zend Framework Manual

MVC 异常
Zend Framework Reference
Zend Framework手册 中文版
Zend_Currency 简介

Zend_Currency

Table of Contents
  • Zend_Currency 简介
  • 如何使用货币
  • Options for currencies
  • What makes a currency?
  • Where is the currency?
  • How does the currency look like?
  • How much is my currency?
  • Calculating with currencies
  • Exchanging currencies
  • Additional informations on Zend_Currency
MVC 异常
Zend Framework Reference
Zend Framework手册 中文版
Zend_Currency 简介
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


Zend_Currency 简介 - Zend Framework Manual

Zend_Currency
Zend_Currency
Zend Framework手册 中文版
如何使用货币

Zend_Currency 简介

Zend_Currency 是Zend_Framework I18n 核心的一部分。它处理所有关于货币、钱的表示和格式。它也提供另外的信息方法，包括货币的本地化信息、关于哪个货币在哪个地区使用等等。

为什么使用 Zend_Currency ？

Zend_Currency 提供了下列函数来处理货币和钱相关的工作。

  • 完全本地支持

    Zend_Currency 支持所有有效地区并因此有能力知道超过 100 中不同的本地货币信息，包括例如货币名称、缩写、钱的符合等等。

  • 可重用的货币定义

    Zend_Currency 不包括货币的值。这就是为什么它的函数不包括在 Zend_Locale_Format 里，但好处是已经定义的货币表示可以被重用。

  • Fluent 接口

    Zend_Currency 按需包含 fluent 接口。

  • 另外的信息方法

    Zend_Currency 包括另外的方法，这方法提供关于哪个地区使用哪种货币或哪种货币被用于被定义的地区的信息。

Zend_Currency
Zend_Currency
Zend Framework手册 中文版
如何使用货币
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Currency
  • Zend_Currency 简介
  • 如何使用货币
  • Options for currencies
  • What makes a currency?
  • Where is the currency?
  • How does the currency look like?
  • How much is my currency?
  • Calculating with currencies
  • Exchanging currencies
  • Additional informations on Zend_Currency


如何使用货币 - Zend Framework Manual

Zend_Currency 简介
Zend_Currency
Zend Framework手册 中文版
Options for currencies

如何使用货币

在自己的程序中使用 Zend_Currency，就是创建一个它的实例，不需要任何参数。它将创建一个带有实际地方、并定义了在这个地方使用的货币的 Zend_Currency 的一个实例。

Example #1 从实际地方创建 Zend_Currency 的实例

期望通过用户（的输入）或环境，你有 'en_US' 设置作为实际地方，通过使用不带参数创建Zend_Currency的实例从地方 'en_US' 来使用实际货币，这导致带美元实例作为带有'en_US'格式规则的实际货币。

$currency = new Zend_Currency();

从 Zend Framework 1.7.0 开始，Zend_Currency 也支持程序范围的地方的用法。你可以简单地如下设置 Zend_Locale 实例到注册表。 如果你想多次使用同一地方，用这个符号你不需要记住对每个实例手工设置地方。

// in your bootstrap file
$locale = new Zend_Locale('de_AT');
Zend_Registry::set('Zend_Locale', $locale);

// somewhere in your application
$currency = new Zend_Currency();

Note: 要知道，如果你的系统没有缺省地方，或者如果你系统的地方不能自动检测到， Zend_Currency 将抛出一个异常。如果这样，你应当手动设置地方。

当然，根据需要，若干参数可以在创建时给出，每个参数都是可选的和被禁止，甚至参数的顺序也可以交换。每个参数的意思描述如下：

  • currency:

    一个地方可以有多种货币，因此第一个参数 'currency' 可通过给出短名称或全名称来定义哪个货币应当被使用。 如果某货币不被任何地方认识，那么就抛出一个异常。货币短名总是三个字母并且是大写。众所周知的货币短名有USD 或 EUR 。想知道所有货币请参考 Zend_Currency 的信息方法。

  • locale:

    第三个参数 'locale' 定义了哪个地方用来格式化货币，给出的地方也将用来获得标准脚本和货币（如果这些参数没有给出时的货币）。

    Note: 注意 Zend_Currency 只接受包括地区的地方，这意味着所有给定的只包括语言地方将抛出一个异常。例如地方 en 将抛出异常而地方 en_US 将返回 USD 作为货币。

Example #2 创建 Zend_Currency 实例的其它例子

// expect standard locale 'de_AT'

// creates an instance from 'en_US' using 'USD' which is default
// currency for 'en_US'
$currency = new Zend_Currency('en_US');

// creates an instance from the actual locale ('de_AT') using 'EUR' as
// currency
$currency = new Zend_Currency();

// creates an instance using 'EUR' as currency, 'en_US' for number
// formating
$currency = new Zend_Currency('en_US', 'EUR');

如果想使用缺省值，你可以禁止任何参数，在处理货币方面没有副作用，例如这在当你不知道某地区的缺省货币很有用。

Note: 许多国家有多种货币，一种正在使用的和一些古老的。如果 'currency' 参数被禁止，那么使用当前货币。例如在地区 'de' 有 'EUR' 和 'DEM'...'EUR' 是当前使用的货币，如果这参数被禁止它将被使用。

从货币创建输出

可以用方法 toCurrency() 把存在的数值转换成格式化的货币输出，它带有一个可以被转换的数值，这个数值可以是任何标准化的数字。

如果有个需要转换的本地化的数字，首先用 Zend_Locale_Format::getNumber() 来标准化，然后用 toCurrency() 创建一个货币输出。

toCurrency(array $options) 接受带有选项的数组，这个选项可用来临时设置成另外的格式或货币表示，关于选项的细节参见 Changing the format of a currency。

Example #3 为货币创建输出

// creates an instance with 'en_US' using 'USD' which is the default
// values for 'en_US'
$currency = new Zend_Currency('en_US');

// prints '$ 1,000.00'
echo $currency->toCurrency(1000);

// prints '$ 1.000,00'
echo $currency->toCurrency(1000, array('format' => 'de_AT'));

// prints '$ ١٬٠٠٠٫٠٠'
echo $currency->toCurrency(1000, array('script' => 'Arab'));

修改货币格式

用来创建 Zend_Currency 实例的格式当然是标准格式，但有时候也需要为自己的意图需要这个格式。

货币输出的格式包括下面部分：

  • 货币符号，短名或名字 :

    或不符号一般显示在货币输出之内，如果需要或重写，它可以被禁止。

  • 货币位置 :

    货币符号的位置一般由地方来自动定义，如果需要，它可以被修改。

  • Script:

    Script 用来显示数字，它的详细用法可以从 Zend_Locale 的文档 被支持的数字 scripts找到。

  • 数字格式 :

    货币的数量 （ 就是钱的数量 ）用在地方( locale )里的格式化规则来格式化，例如在英语中 ',' 用来分离每一千，在德国就用 '.'符号（例如一百万，在英语中就是1,000,000 而在德语中就是1.000.000 好像在德语中容易和小数点混淆 by Jason Qi）。

如果确实需要修改格式，你可以用 setFormat() 方法。它带有一个数组，包括所有你向修改的选项。options 数组支持下列设置：

  • position: 定义货币显示位置，从 this table 可以找到被支持的位置。

  • script: 定义哪个 script 被用来显示数字，大部分地方的缺省的 script 是 'Latn' ，它包括数字 0 到 9 。并且其它的 scripts 如 'Arab'(Arabian) 也可以用。所有被支持的 scipts 可以从 this table 找到。

  • format: 定义哪个地方（locale）用来显示数字，数字格式包括千为分隔符。如果没有指定格式，就使用 Zend_Currency 对象中的地方（ locale ）。

  • display: 定义货币中的哪个部分用来显示货币表示，有四中表示法可用，都在 this table 中描述。

  • precision: 定义用于货币表示的精确位数，它的缺省值是2。

  • name: 定义被显示的货币名称，它重写通过创建 Zend_Currency 产生的任何货币名称。

  • currency: 定义被显示的国际缩写，它重写通过创建 Zend_Currency 产生的任何缩写。

  • symbol: 定义被显示的货币符号，它重写通过创建 Zend_Currency 产生的任何符号。

选择货币描述的常量
常量 | 描述
NO_SYMBOL | 不显示任何货币表示
USE_SYMBOL | 显示货币符号
USE_SHORTNAME | 显示三个字母的国际货币缩写
USE_NAME | 显示货币全名
选择货币位置的常量
常量 | 描述
STANDARD | 设置在地方里定义标准位置
RIGHT | 在数的右面显示货币表示符
LEFT | 在数值的左面显示货币表示符

Example #4 修改货币的显示格式

// creates an instance with 'en_US' using 'USD', 'Latin' and 'en_US' as
// these are the default values from 'en_US'
$currency = new Zend_Currency('en_US');

// prints 'US$ 1,000.00'
echo $currency->toCurrency(1000);

$currency->setFormat('display' => Zend_Currency::USE_NAME,
                     'position' => Zend_Currency::RIGHT);
// prints '1.000,00 US Dollar'
echo $currency->toCurrency(1000);

$currency->setFormat('name' => 'American Dollar');
// prints '1.000,00 American Dollar'
echo $currency->toCurrency(1000);

Zend_Currency 的信息方法

当然，Zend_Currency 也支持从 Zend_Locale 获得任何存在的和许多古老货币的信息。支持的方法是：

  • getSymbol():

    返回实际货币或给定货币的已知符号。例如 $ 在 en_US 地方表示美元。

  • getShortName():

    返回实际货币或给定货币的缩写。例如 USD 在 en_US 地方表示美元。

  • getName():

    返回实际货币或给定货币的全名。例如 US Dollar 在 en_US 地方表示美元。

  • getRegionList():

    返回实际货币或给定被使用货币的地区列表。因为某种货币可能被用于多个地区，所以返回值总是一个数组。

  • getCurrencyList():

    返回用于给定地区的已知货币的列表。

函数 getSymbol()、 getShortName() 和 getName() 带两个可选的参数。如果没有给出参数，期望的数据将从当前设置货币返回。第一个参数是货币的短名，短名总是三个字母，例如 EUR 是欧元，USD 是美元。第二个参数定义从哪个地方（ locale ）读数据。如果没有给出地方，就使用当前使用的地方设置。

Example #5 从货币中获取信息

// creates an instance with 'en_US' using 'USD', 'Latin' and 'en_US'
// as these are the default values from 'en_US'
$currency = new Zend_Currency('en_US');

// prints '$'
echo $currency->getSymbol();

// prints 'EUR'
echo $currency->getShortName('EUR');

// prints 'Österreichische Schilling'
echo $currency->getName('ATS', 'de_AT');

// returns an array with all regions where USD is used
print_r($currency->getRegionList();

// returns an array with all currencies which were ever used in this
// region
print_r($currency->getCurrencyList('de_AT');

设置新缺省值

setLocale 方法允许设置新的地方给 Zend_Currency 。当调用这个函数所有的货币的缺省值就被重写，包括货币名、缩写和符号。

Example #6 设置新地方

// 获得 US 货币
$currency = new Zend_Currency('en_US');
print $currency->toCurrency(1000);

// 获得 AT 货币
$currency->setLocale('de_AT');
print $currency->toCurrency(1000);

加速 Zend_Currency

通过 Zend_Cache 的使用可以加速 Zend_Currency 的工作。通过使用静态方法 Zend_Currency::setCache($cache) ，它接受一个选项，Zend_Cache 适配器，当设置它，Zend_Currency 方法的本地化数据就被缓存。 也有个静态方法 Zend_Currency::getCache() 方便你的使用。

Example #7 缓存货币

// 创建一个缓存对象
$cache = Zend_Cache::factory('Core',
                             'File',
                             array('lifetime' => 120,
                                   'automatic_serialization' => true),
                             array('cache_dir'
                                       => dirname(__FILE__) . '/_files/'));
Zend_Currency::setCache($cache);
Zend_Currency 简介
Zend_Currency
Zend Framework手册 中文版
Options for currencies
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Currency
  • Zend_Currency 简介
  • 如何使用货币
  • Options for currencies
  • What makes a currency?
  • Where is the currency?
  • How does the currency look like?
  • How much is my currency?
  • Calculating with currencies
  • Exchanging currencies
  • Additional informations on Zend_Currency


Options for currencies - Zend Framework Manual

如何使用货币
Zend_Currency
Zend Framework手册 中文版
What makes a currency?

Options for currencies

Depending on your needs, several options can be specified at instantiation. All of this options have default values. But sometimes it is necessary to define how your currencies will be rendered. This includes for example:

  • Currency symbol, shortname or name:

    Zend_Currency knows all currency names, abbreviations and signs. But sometimes you could be in need to define the string which has to be displayed as replacement for a currency.

  • Currency position:

    The position of the currency symbol is automatically defined. But sometimes you could be in need to define it manually.

  • Script:

    You could define the script which shall be used to display digits. Detailed information about scripts and their usage can be found in Zend_Locale's chapter Numeral System Conversion.

  • Number formatting:

    The amount of currency (generally known as money value) is formatted by usaging the formatting rules defined by the locale. For example is the ',' sign in english used as separator for thousands, but in german as precision sign.

The following list mentions all options which could be set. They can eighter be set at initiation or by using the setFormat() method. In any case you have to give this options as array.

  • currency: Defines the abbreviation which can be displayed.

  • display: Defines which part of the currency should be used for displaying the currency representation. There are 4 representations which can be used and which are all described in this table.

  • format: Defines the format which should be used for displaying numbers. This number-format includes for example the thousand separator. You can either use a default format by giving a locale identifier, or define the number-format manually. If no format is set the locale from the Zend_Currency object will be used. See the chapter about number formatting for details.

  • locale: Defines a locale for this currency. It will be used for detecting the default values when other settings are omitted. Note that when you don't set a locale yourself, it will be detected automatically which could lead to problems.

  • name: Defines the full currency name which can be displayed.

  • position: Defines the position at which the currency description should be displayed. The supported positions are described this section.

  • precision: Defines the precision which should be used for the currency representation. The default value depends on the locale and is for most locales 2.

  • script: Defined which script should be used for displaying digits. The default script for most locales is 'Latn', which includes the digits 0 to 9. Other scripts such as 'Arab' (Arabian) are using other digits. See the chapter about numbering systems for details and available options.

  • service: Defines the exchange service which has to be used when calculating with different currencies.

  • symbol: Defines the currency symbol which can be displayed.

  • value: Defines the currency amount (money value). Using this option you should also set the service option.

As you can see there is much which could be changed. Still as already mentioned the default values for this settings conform the official standard for currency represenation in every country.

如何使用货币
Zend_Currency
Zend Framework手册 中文版
What makes a currency?
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Currency
  • Zend_Currency 简介
  • 如何使用货币
  • Options for currencies
  • What makes a currency?
  • Where is the currency?
  • How does the currency look like?
  • How much is my currency?
  • Calculating with currencies
  • Exchanging currencies
  • Additional informations on Zend_Currency


What makes a currency? - Zend Framework Manual

Options for currencies
Zend_Currency
Zend Framework手册 中文版
Where is the currency?

What makes a currency?

The currency consists of several informations. A name, a abbreviation and a sign. Each of these could be relevant to be displayed, but only one at the same time. It would not be a good practice to display something like "USD 1.000 $".

Therefor Zend_Currency supports the definition of the currency information which has to be rendered. The following constants can be used:

Rendered informations for a currency
Constant | Description
NO_SYMBOL | No currency representation will be rendered at all
USE_SYMBOL | The currency symbol will be rendered. For US Dollar this would be '$'
USE_SHORTNAME | The abbreviation for this currency will be rendered. For US Dollar this would be 'USD'. Most abbreviations consist of 3 characters
USE_NAME | The full name for this currency will be rendered. For US Dollar the full name would be "US Dollar"

Example #1 Selecting the currency description

Let's assume that your client has again set "en_US" as locale. Using no option the returned value could look like this:

  1. $currency = new Zend_Currency(
  2.     array(
  3.         'value' => 100,
  4.     )
  5. );
  6.
  7. print $currency; // Could return '$ 100'

By giving the proper option you can define what information which has to be rendered.

  1. $currency = new Zend_Currency(
  2.     array(
  3.         'value'   => 100,
  4.         'display' => Zend_Currency::USE_SHORTNAME,
  5.     )
  6. );
  7.
  8. print $currency; // Could return 'USD 100'

Without providing the display the currency sign will be used when rendering the object. When the currency has no sign, the abbreviation will be used as replacement.

Note: Not all currencies have signs
 You should note that not all currencies have default currency signs. This means, that when there is no default sign, and you set the sign to be rendered, you will not have a rendered currency at all because the sign is an empty string.

Sometimes it is necessary to change the default informations. You can set each of the three currency informations independently by giving the proper option. See the following example.

Example #2 Changing the currency description

Let's assume that your client has again set "en_US" as locale. But now we don't want to use the default settings but set our own description. This can simply be done providing the proper option:

  1. $currency = new Zend_Currency(
  2.     array(
  3.         'value' => 100,
  4.         'name'  => 'Dollar',
  5.     )
  6. );
  7.
  8. print $currency; // Could return 'Dollar 100'

You could also set a sign or an abbreviations yourself.

  1. $currency = new Zend_Currency(
  2.     array(
  3.         'value'    => 100,
  4.         'symbol' => '$$$',
  5.     )
  6. );
  7.
  8. print $currency; // Could return '$$$ 100'

Note: Automatic display settings
 When you set a name, abbreviation or sign yourself, than this new information will automatically be set to be rendered. This simplification prevents you from setting the proper display option when you set a information.
So using the sign option you can omit display and don't neet to setting it to 'USE_SYMBOL'.

Options for currencies
Zend_Currency
Zend Framework手册 中文版
Where is the currency?
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Currency
  • Zend_Currency 简介
  • 如何使用货币
  • Options for currencies
  • What makes a currency?
  • Where is the currency?
  • How does the currency look like?
  • How much is my currency?
  • Calculating with currencies
  • Exchanging currencies
  • Additional informations on Zend_Currency


Where is the currency? - Zend Framework Manual

What makes a currency?
Zend_Currency
Zend Framework手册 中文版
How does the currency look like?

Where is the currency?

The position where the currency sign or name will be displayed depends on the locale. Still, when you want to define this setting yourself you have to use the display option and provide one of the following constants:

Available positions for the currency
Constant | Description
STANDARD | Sets the standard position as defined within the locale
RIGHT | Displays the currency representation at the right side of the value
LEFT | Displays the currency representation at the left side of the value

Example #1 Setting the currency position

Let's assume that your client has again set "en_US" as locale. Using no option the returned value could look like this:

  1. $currency = new Zend_Currency(
  2.     array(
  3.         'value' => 100,
  4.     )
  5. );
  6.
  7. print $currency; // Could return '$ 100'

So by using the default setting the currency (in our case $) could eighter be rendered left or right from the value. Now let's define a fixed position:

  1. $currency = new Zend_Currency(
  2.     array(
  3.         'value'    => 100,
  4.         'position' => Zend_Currency::RIGHT,
  5.     )
  6. );
  7.
  8. print $currency; // Could return '100 $';

Note that in the second snippet the position of USD is fixed regardless of the used locale or currency.

What makes a currency?
Zend_Currency
Zend Framework手册 中文版
How does the currency look like?
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Currency
  • Zend_Currency 简介
  • 如何使用货币
  • Options for currencies
  • What makes a currency?
  • Where is the currency?
  • How does the currency look like?
  • How much is my currency?
  • Calculating with currencies
  • Exchanging currencies
  • Additional informations on Zend_Currency


How does the currency look like? - Zend Framework Manual

Where is the currency?
Zend_Currency
Zend Framework手册 中文版
How much is my currency?

How does the currency look like?

How the value of a currency will be rendered depends mainly on the used locale. There are several informations which are set by the locale. Each of them can manually be overridden by using the proper option.

For example, most locales are using the latin script for rendering numbers. But there are languages like "Arabic" which are using other digits. And when you have an arabic website you may also want to render other currencies by using the arabic script. See the following example:

Example #1 Using a custom script

Let's expect that we are again using our "Dollar" currency. But now we want to render our currency by using the arabic script.

  1. $currency = new Zend_Currency(
  2.     array(
  3.         'value'  => 1000,
  4.         'script' => 'Arab',
  5.     )
  6. );
  7.
  8. print $currency; // Could return '$ ١٬٠٠٠٫٠٠'

For more informations about available scripts look into Zend_Locale's chapter about numbering systems.

But also the formatting of a currency number (money value) can be changed. Per default it depends on the used locale. It includes the separator which will be used between thousands, which sign will be used as decimal point, and also the used precision.

  1. $currency = new Zend_Currency(
  2.     array(
  3.         'value'    => 1000,
  4.         'currency' => 'USD'
  5.         'format'   => 'de',
  6.     )
  7. );
  8.
  9. print $currency; // Could return '$ 1.000'

There are two ways to define the format which will be used. You can eighter give a locale or define a format manually.

When you are using a locale for defining the format all is done automatically. The locale 'de', for example, defines '.' as separator for thousands and ',' as decimal point. Within english this is reversed.

  1. $currency_1 = new Zend_Currency(
  2.     array(
  3.         'value'    => 1000,
  4.         'currency' => 'USD'
  5.         'format'   => 'de',
  6.     )
  7. );
  8.
  9. $currency_2 = new Zend_Currency(
  10.     array(
  11.         'value'    => 1000,
  12.         'currency' => 'USD'
  13.         'format'   => 'en',
  14.     )
  15. );
  16.
  17. print $currency_1; // Could return '$ 1.000'
  18. print $currency_2; // Could return '$ 1,000'

When you define it manually then you must conform the format as described in this chapter about localizing. See the following:

  1. $currency = new Zend_Currency(
  2.     array(
  3.         'value'    => 1000,
  4.         'currency' => 'USD'
  5.         'format'   => '#0',
  6.     )
  7. );
  8.
  9. print $currency; // Could return '$ 1000'

In the above snippet we deleted the separator and also the precision.

Where is the currency?
Zend_Currency
Zend Framework手册 中文版
How much is my currency?
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Currency
  • Zend_Currency 简介
  • 如何使用货币
  • Options for currencies
  • What makes a currency?
  • Where is the currency?
  • How does the currency look like?
  • How much is my currency?
  • Calculating with currencies
  • Exchanging currencies
  • Additional informations on Zend_Currency


How much is my currency? - Zend Framework Manual

How does the currency look like?
Zend_Currency
Zend Framework手册 中文版
Calculating with currencies

How much is my currency?

When you are working with currencies then you normally want to display an amount of money. And when you work with different currencies then you have to do this with three different things. The amount you want to display, the precision you want to use, and probably the exchange rate.

Working with currency values

The currency value, a.k.a. the money, you want to use can easily be set by using the value option.

  1. $currency = new Zend_Currency(
  2.     array(
  3.         'value'    => 1000,
  4.         'currency' => 'USD',
  5.     )
  6. );
  7.
  8. print $currency; // Could return '$ 1.000'

Using the setFormat() method with this array option, and also by using the setValue() method you can set the value afterwards.

  1. $currency = new Zend_Currency(
  2.     array(
  3.         'value'    => 1000,
  4.         'currency' => 'USD',
  5.     )
  6. );
  7.
  8. print $currency->setValue(2000); // Could return '$ 2.000'

With the getValue() method you will get the actual set value.

Using precision on currencies

When working with currencies they you probably also have to handle precision. Most currencies use a precision of 2. This means that when you have 100 US dollars you could also have 50 cents. The related value is simply a floating value.

  1. $currency = new Zend_Currency(
  2.     array(
  3.         'value'    => 1000.50,
  4.         'currency' => 'USD',
  5.     )
  6. );
  7.
  8. print $currency; // Could return '$ 1.000,50'

Of course, as the default precision is 2, you will get '00' for the decimal value when there is no precision to display.

  1. $currency = new Zend_Currency(
  2.     array(
  3.         'value'    => 1000,
  4.         'currency' => 'USD',
  5.     )
  6. );
  7.
  8. print $currency; // Could return '$ 1.000,00'

To get rid of this default precision you could simply use the precision option and set it to '0'. And you can set any other precision you want to use between 0 and 9. All values will be rounded or streched when they don't fit the set precision.

  1. $currency = new Zend_Currency(
  2.     array(
  3.         'value'     => 1000,30,
  4.         'currency'  => 'USD',
  5.         'precision' => 0
  6.     )
  7. );
  8.
  9. print $currency; // Could return '$ 1.000'
How does the currency look like?
Zend_Currency
Zend Framework手册 中文版
Calculating with currencies
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Currency
  • Zend_Currency 简介
  • 如何使用货币
  • Options for currencies
  • What makes a currency?
  • Where is the currency?
  • How does the currency look like?
  • How much is my currency?
  • Calculating with currencies
  • Exchanging currencies
  • Additional informations on Zend_Currency


Calculating with currencies - Zend Framework Manual

How much is my currency?
Zend_Currency
Zend Framework手册 中文版
Exchanging currencies

Calculating with currencies

When working with currencies you will sometimes also have to calculate with them. Zend_Currency allows you to do this with some simple methods. The following methods are supported for calculation:

  • add(): This method adds the given currency to the existing currency object.

  • sub(): This method substracts the given currency from the existing currency object.

  • div(): This method divides the given currency from the existing currency object.

  • mul(): This method multiplies the given currency with the existing currency object.

  • mod(): This method calculates the remaining value (modulo) from dividing the given currency from the existing currency object.

  • compare(): This method compares the given currency with the existing currency object. When both values are equal it returns '0'. When the existing currency value is greater than the given, this method will return 1. Otherwise you will get '-1' returned.

  • equals(): This method compares the given currency with the existing currency object. When both values are equal it returns TRUE, otherwise FALSE.

  • isMore(): This method compares the given currency with the existing currency object. When the existing currency is greater than the given one, you will get TRUE in return, otherwise FALSE.

  • isLess(): This method compares the given currency with the existing currency object. When the existing currency is less than the given one, you will get TRUE in return, otherwise FALSE.

As you can see the multiple methods allow any kind of calculation with Zend_Currency. See the next snippets as example:

  1. $currency = new Zend_Currency(
  2.     array(
  3.         'value'    => 1000,
  4.         'currency' => 'USD',
  5.     )
  6. );
  7.
  8. print $currency; // Could return '$ 1.000,00'
  9.
  10. $currency->add(500);
  11. print $currency; // Could return '$ 1.500,00'
  1. $currency_2 = new Zend_Currency(
  2.     array(
  3.         'value'    => 500,
  4.         'currency' => 'USD',
  5.     )
  6. );
  7.
  8. if ($currency->isMore($currency_2)) {
  9.     print "First is more";
  10. }
  11.
  12. $currency->div(5);
  13. print $currency; // Could return '$ 200,00'
How much is my currency?
Zend_Currency
Zend Framework手册 中文版
Exchanging currencies
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Currency
  • Zend_Currency 简介
  • 如何使用货币
  • Options for currencies
  • What makes a currency?
  • Where is the currency?
  • How does the currency look like?
  • How much is my currency?
  • Calculating with currencies
  • Exchanging currencies
  • Additional informations on Zend_Currency


Exchanging currencies - Zend Framework Manual

Calculating with currencies
Zend_Currency
Zend Framework手册 中文版
Additional informations on Zend_Currency

Exchanging currencies

Within the previous section we discussed currency calculations. But as you can imaging calculating currencies does often mean to calculate different currencies from different countries.

In this case the currencies have to be exchanged so that both use the same currency. Within real live this information is available by banks or by daily papers. But as we are in web, we should use available exchange services. Zend_Currency allows their usage with a simple callback.

First let's write a simple exchange service.

  1. class SimpleExchange implements Zend_Currency_CurrencyInterface
  2. {
  3.     public function getRate($from, $to)
  4.     {
  5.         if ($from !== "USD") {
  6.             throw new Exception('We can only exchange USD');
  7.         }
  8.
  9.         switch ($to) {
  10.             case 'EUR':
  11.                 return 0.5;
  12.             case 'JPE':
  13.                 return 0.7;
  14.        }
  15.
  16.        throw new Exception('Unable to exchange $to');
  17.     }
  18. }

We have now created a manual exchange service. It will not fit the real live, but it shows you how currency exchange works.

Your exchange class must implement the Zend_Currency_CurrencyInterface interface. This interface requires the single method getRate() to be implemented. This method has two parameters it will receive. Both are the short names for the given currencies. Zend_Currency on the other side needs the exchange rate to be returned.

In a living exchange class you would probably ask the service provider for the correct exchange rates. For our example the manual rate will be ok.

Now we will simply attach our exchange class with Zend_Currency. There are two ways to do this. Eigher by attaching a instance of the Exchange class, or by simply giving a string with the classname.

  1. $currency = new Zend_Currency(
  2.     array(
  3.         'value'    => 1000,
  4.         'currency' => 'USD',
  5.     )
  6. );
  7.
  8. $service  = new SimpleExchange();
  9.
  10. // attach the exchange service
  11. $currency->setService($service);
  12.
  13. $currency_2 = new Zend_Currency(
  14.     array(
  15.         'value'    => 1000,
  16.         'currency' => 'EUR',
  17.     )
  18. );
  19.
  20. print $currency->add($currency2);

The above example will return '$ 3.000' because the 1.000 EUR will be converted by a rate of 2 to 2.000 USD.

Note: Calculation without exchange service
 When you try to calculate two currency objects which do not use the same currency and have no exchange service attached, you will get an exception. The reason is that Zend_Currency is then not able to switch between the different currencies.

Calculating with currencies
Zend_Currency
Zend Framework手册 中文版
Additional informations on Zend_Currency
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Currency
  • Zend_Currency 简介
  • 如何使用货币
  • Options for currencies
  • What makes a currency?
  • Where is the currency?
  • How does the currency look like?
  • How much is my currency?
  • Calculating with currencies
  • Exchanging currencies
  • Additional informations on Zend_Currency


Additional informations on Zend_Currency - Zend Framework Manual

Exchanging currencies
Zend_Currency
Zend Framework手册 中文版
Zend_Date

Additional informations on Zend_Currency

Currency informations

Sometimes it is necessary to get informations which are related to a currency. Zend_Currency provides you with several methods to get this informations. Available methods include the following:

  • getCurrencyList(): Returns a list of all currencies which are used in the given region as array. Defaults to the objects locale when no region has been given.

  • getLocale(): Returns the set locale for the actual currency.

  • getName(): Returns the full name for the actual currency. When there is no full name available for the actual currency, it will return the abbreviation for it.

  • getRegionList(): Returns a list of all regions where this currency is used as array. Defaults to the objects currency when no currency has been given.

  • getService(): Returns the set exchange service object for the actual currency.

  • getShortName(): Returns the abbreviation for the actual currency.

  • getSymbol(): Returns the currency sign for the currency. When the currency has no symbol, then it will return the abbreviation for it.

  • getValue(): Returns the set value for the actual currency.

Let's see some code snippets as example:

  1. $currency = new Zend_Currency();
  2.
  3. var_dump($currency->getValue());
  4. // returns 0
  5.
  6. var_dump($currency->getRegionList());
  7. // could return an array with all regions where USD is used
  8.
  9. var_dump($currency->getRegionList('EUR'));
  10. // returns an array with all regions where EUR is used
  11.
  12. var_dump($currency->getName());
  13. // could return 'US Dollar'
  14.
  15. var_dump($currency->getName('EUR'));
  16. // returns 'Euro'

As you can see, several methods allow to use additional parameters to override the actual object to get informations for other currencies. Omitting this parameters will return informations from the actual set currency.

Currency Performance Optimization

Zend_Currency's performance can be optimized using Zend_Cache. The static method Zend_Currency::setCache($cache) accepts one option: a Zend_Cache adapter. If the cache adapter is set, the localization data which is used by Zend_Currency will be cached. Additionally there are some static methods for manipulating the cache: getCache(), hasCache(), clearCache() and removeCache().

Example #1 Caching currencies

  1. // creating a cache object
  2. $cache = Zend_Cache::factory('Core',
  3.                              'File',
  4.                              array('lifetime' => 120,
  5.                                    'automatic_serialization' => true),
  6.                              array('cache_dir'
  7.                                        => dirname(__FILE__) . '/_files/'));
  8. Zend_Currency::setCache($cache);
Exchanging currencies
Zend_Currency
Zend Framework手册 中文版
Zend_Date
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Currency
  • Zend_Currency 简介
  • 如何使用货币
  • Options for currencies
  • What makes a currency?
  • Where is the currency?
  • How does the currency look like?
  • How much is my currency?
  • Calculating with currencies
  • Exchanging currencies
  • Additional informations on Zend_Currency


Zend_Date - Zend Framework Manual

Additional informations on Zend_Currency
Zend Framework Reference
Zend Framework手册 中文版
简介

Zend_Date

Table of Contents
  • 简介
  • 操作理论
  • 基本方法
  • Zend_Date API 概述
  • 生成日期
  • 一般日期函数的常量
  • Working 范例
Additional informations on Zend_Currency
Zend Framework Reference
Zend Framework手册 中文版
简介
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


简介 - Zend Framework Manual

Zend_Date
Zend_Date
Zend Framework手册 中文版
操作理论

简介

Zend_Date 组件提供了一个详细而简单的 API 用来处理日期和时间。它的方法接受广泛的信息，包括日期部分、 各种组合产生的许多功能和超出 PHP 日期相关函数的可能行。对于最新的手册，请参考 » 在线手册（及时和 Subversion 同步）。

虽然保持简单是我们的目标，但是日期和时间的本地化修改、合并和比较是不可避免的复杂。 日期、还有时间在不同的地方有不同的写法。例如，一些地方月在前面，一些地方年在前面。 关于更多处理本地化和标准化的信息，请参考 Zend_Locale。

Zend_Date 在许多语言中也支持月名的缩写。 Zend_Locale 简化本地的月和星期名到时间戳的标准化。 这样，它们在其它地区就显示为本地化的格式。 Zend_Locale

永远设置缺省时区

在 PHP 或 Zend Framework 中使用任何日期相关的函数之前， 通过使用 date.timezone php.ini 的设置来设置 TZ 环境变量，或者使用 » date_default_timezone_set()。 首先确保你的程序有个正确的缺省时区， 在 PHP 中，通过根据用户的期望设置一个缺省的时区，我们可以调整所有日期和时间相关的函数为特定的用户来工作。 时区设置的全部列表，请参考 » CLDR Timezone Identifier List。

Example #1 设置一个缺省的时区

// timezone for an American in California
date_default_timezone_set('America/Los_Angeles');
// timezone for a German in Germany
date_default_timezone_set('Europe/Berlin');
当创建 Zend_Date 实例时，它们的时区就自动地变成当前缺省时区！ 这样，时区设置将有效地解决任何夏时制（DST）问题，不需要显式地指定夏时制。

请记住时区 UTC 和 GMT 不包括夏令时。 这意味着即使你定义了 Zend_Date 工作于 DST，对于设置为 UTC 或 GMT 的 Zend_Date 实例，它也自动切换回来。

为什么使用 Zend_Date?

Zend_Date 提供下列功能，它扩展了 PHP 日期函数的功能：

  • 简单的 API

    Zend_Date 提供了非常简单的 API，它结合了四种编程语言中的最好的日期/时间函数。 例如在一行中可以加或者比较两个时间。

  • 完全国际化

    支持超过 130 中语言的月和星期名的全称和缩写。以和地方相关联的常规的格式支持使用本地化月和星期名的输入和输出的方法。

  • 无限制的时间戳

    尽管 PHP 5.2 声明 “有效的时间戳范围一般是从 1901年12月13日星期五20:45:54 GMT 到 2038年1月19日星期二 2038 03:14:07 GMT”， Zend_Date 在 BCMath 扩展的帮助下，还是支持一个几乎无限制的范围。 如果 BCMath 不可用，Zend_Date 将只把对时间戳的支持范围减小到你的服务器所支持的 float 类型的范围。 “浮点数的大小和平台无关，虽然最大数 ~1.8e308 是带有大概精确到 14 位十进制数的一个值（64位 IEEE 格式）”[» http://www.php.net/float]。 另外，由于浮点数本身的限制，浮点数的误差可能会带来计算的错误。为避免这个问题，如果 BCMath 扩展可用，ZF I18n 组件就使用它。

  • 支持 ISO_8601 日期规范

    支持ISO_8601 日期规范。即使部分兼容 ISO_8601 日期规范将被识别。当和数据库一起使用时，这些日期格式特别有用。 例如，即使 MsSQL 和 » MySQL 有点不同，Zend_Date 都用 Zend_Date::ISO_8601 格式规范常量来支持它们。当日期字符串符合 "Y/m/d" or "Y-m-d H:i:s" 根据 PHP date() 格式令牌，使用 Zend_Date 的内置的 ISO 8601 日期格式。

  • 计算日出和日落

    对于任何地方的一天，可以显示日出和日落的时间，这样你就不会错过一秒的白天时间来工作于你喜欢的 PHP 项目 :)

Zend_Date
Zend_Date
Zend Framework手册 中文版
操作理论
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Date
  • 简介
  • 操作理论
  • 基本方法
  • Zend_Date API 概述
  • 生成日期
  • 一般日期函数的常量
  • Working 范例


操作理论 - Zend Framework Manual

简介
Zend_Date
Zend Framework手册 中文版
基本方法

操作理论

为什么在 Zend Framework 中只有一个 Zend_Date 类来处理日期和时间？

很多语言把处理时间和日历日期分成两个类，然而，Zend Framework 为简单而努力。在很多情况下，迫使开发者为时间和日期在不同的方法中管理不同的对象变成一种负担。 因为 Zend_Date 方法支持不明确的日期，它可能不包括所有部分（era 、年、月、日、小时、分钟、秒、时区），所以开发者可以享受灵活性和轻松地使用同一类和同一方法来进行处理（例如：加、减、比较、合并日期等）。当渴望在短期内熟悉这些交互操作，把处理这些日期的片段分成多个类会把事情弄的复杂。一个单个的类为相似的操作减少了代码重复，也不需要复杂的继承等级结构。

内部（Internals）

  • UNIX 时间戳（Timestamp）

    所有日期和时间，甚至不明确的（例如，没有年），在内部表示为绝对的时间点，用期望的时间点和1970年1月1日 00:00:00 GMT/UTC 之间的差来作为UNIX 时间戳来表示。这是唯一的可能，因为 Zend_Date 既不限于 UNIX 时间戳也不限于整数值。BCMath 扩展被要求来支持非常大的在星期五，1901年12月13日 20:45:54 GMT 到星期二，2038年1月19日 03:14:07 GMT范围之外的日期。另外，因为浮点数据类型和凑整固有的限制，细小的数学错误会产生，除非使用 BCMath 扩展。

  • 日期部分为时间戳（ timestamp）偏移量

    这样，一个表示三小时的实例对象将被表示为在 1970年1月1日 00:00:00 GMT/UTC 之后的三小时 － 例如 0 + 3 * 60 * 60 = 10800 。

  • PHP 函数

    Zend_Date 尽可能经常使用 PHP 函数提高性能。

简介
Zend_Date
Zend Framework手册 中文版
基本方法
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Date
  • 简介
  • 操作理论
  • 基本方法
  • Zend_Date API 概述
  • 生成日期
  • 一般日期函数的常量
  • Working 范例


基本方法 - Zend Framework Manual

操作理论
Zend_Date
Zend Framework手册 中文版
Zend_Date API 概述

基本方法

下面的章节用例子来说明 Zend_Date 的基本用法。对于本手册，"dates" 总是暗示 带有时间的日历日期，即使没有显式说明，反之亦然。没有指定的部分就在内部缺省为 “零”。 这样，添加一个没有日历日期和一个时间值为 12 小时到另一个只包含日历日期的日期上，就变成那个被添加的日期的“中午”。

只设置一个指定的日期，没有时间部分，那么时间就设置为 00:00:00。相反，只设置一个指定的时间暗示在内部日期 设置为 01.01.1970 加上等同已经发生的小时，分钟和秒的秒数。一般来说，人们从开始点测量东西，如 A.D. 0年。 然而，许多软件系统使用1970年的第一秒作为开始点，并表示为时间戳偏移量。

当前日期

不带任何参数，构造一个实例缺省地返回一个用PHP的 time()函数获得 » UNIX 时间戳 当前本地日期的对象。请确认你的PHP环境有正确的 缺省时区。

Example #1 生成当前日期

$date = new Zend_Date();

// Output of the current timestamp
print $date;

Zend_Date 的例子

对于不熟悉在其他语言或框架中的日期对象的开发者，回顾一下 Zend_Date 的基本方法是一个好的开始。 下面对每个方法提供了一个小的范例。

输出日期

在 Zend_Date 对象里的日期可用 get() 方法获得为本地化的整数或字符串。 在后面的章节，我们将解释许多可用的选项。

Example #2 get() - 输出日期

$date = new Zend_Date();

// Output of the desired date
print $date->get();

设置日期

set() 方法修改存储在对象里的日期，并以时间戳（不是对象）的形式返回最终的日期值。 再强调一下， 在后面的章节，我们将解释许多可用的选项。

Example #3 set() - 设置日期

$date = new Zend_Date();

// Setting of a new time
$date->set('13:00:00',Zend_Date::TIMES);
print $date->get(Zend_Date::W3C);

加减日期

用 add() 来加两个日期常常是以时间的形式把一个真是的日期加到一个表示日期部分的假的时间戳， 如下面例子所示的12小时。add() 和 sub() 都使用相同的选项 set()， 我们将在后面解释。

Example #4 add() - 加日期

$date = new Zend_Date();

// changes $date by adding 12 hours
$date->add('12:00:00', Zend_Date::TIMES);

echo "Date via get() = ", $date->get(Zend_Date::W3C), "\n";

// use magic __toString() method to call Zend_Date's toString()
echo "Date via toString() = ", $date, "\n";

比较日期

所有基本的 Zend_Date 方法都可以操作整个包含在对象里的日期，或者日期部分，如和一个绝对值比较分钟数。 例如使用 compare() 比较当前时间里的当前分钟可以和一个特定的分钟数，示例如下。

Example #5 compare() - 比较日期

$date = new Zend_Date();

// Comparation 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";
}

对简单的相等比较，使用 equals()，它返回一个布尔值。

Example #6 equals() - 识别日期或日期部分

$date = new Zend_Date();

// Comparation of the two dates
if ($date->equals(10, Zend_Date::HOUR)) {
    print "It's 10 o'clock. Time to get to work.";
} else {
    print "It is not 10 o'clock. You can keep sleeping.";
}
操作理论
Zend_Date
Zend Framework手册 中文版
Zend_Date API 概述
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Date
  • 简介
  • 操作理论
  • 基本方法
  • Zend_Date API 概述
  • 生成日期
  • 一般日期函数的常量
  • Working 范例


Zend_Date API 概述 - Zend Framework Manual

基本方法
Zend_Date
Zend Framework手册 中文版
生成日期

Zend_Date API 概述

虽然 Zend_Date API 简单并单一，但是通过操作和操作数的丰富组合，它的设计灵活而强大。

Zend_Date 选项

选择日期格式类型

有若干方法使用日期格式串，和 PHP 的 date() 类似。如果你觉得用 PHP 的日期格式指示器（ specifier） 比用 ISO 格式指示器舒服， 那么你可以使用 Zend_Date::setOptions(array('format_type' => 'php')) 。 然后，对所有接受 $format 参数的函数使用 PHP 的日期格式指示器。 使用 Zend_Date::setOptions(array('format_type' => 'iso')) 来切换回只支持 ISO 日期格式的缺省模式。 所支持格式代码，参见 使用 PHP 的 date() 格式指定器的自定义输出格式

DST 和日期数学

当处理日期时，有时候需要考虑 DST（夏令时）更改的影响，一般是加上或减去一个小时。例如，在DST更改前加 上月份到日期，如果结果是在DST更改之后，那么结果将会多或少一个小时。对于边界日期，如一个月的第一天或 最后一天的午夜，添加足够的月份数来跨国日期边界会导致日期丢失一个小时并变成前面月份的最后一个小时，出现 "off by 1" 错误。 为了避免这个情况发生，通过使用 fix_dst 选项来忽略 DST 更改。当跨过夏天/冬天 DST 边界，一般要加减一个小时。 例如，如果日期的时间部分是 00:00:00， 日期算术跨过春季 DST 会导致日期比预期少一天。 因为 Zend_Date 基于时间戳，而不是带有时间组件的日历日期，时间戳丢失一个小时导致日期在日历天上比预期少一天。 为了防止这样的问题，使用选项 fix_dst，它缺省为 true，这样 DST 在日期“算术”（addMOnth(), subMonth()）里无效。 当执行日期“算术“，使用 Zend_Date::setOptions(array('fix_dst' => false)) 使日期加减考虑 DST 的调整。

如果在Zend_Date实例里的当前时区设置为 UTC 或 GMT， 就不用 'fix_dst' 选项， 这是因为这两个时区和 DST 没有关系。当你又为这个实例的时区修改为不是 UTC 或 GMT 的时区，那么先前设置的 'fix_dst'选项将用于日期“算术”。

月份计算

当从一个日期加减月份时，如果原来的日期接近月末，结果在某月的某天可能不是所期望的。 例如，当 1月31日加上1个月是，熟悉 SQL的人将以为结果是 2月28日。另一方面，熟悉 Excel 和 OpenOffice的人将认为结果是 3月3日。 这种问题只发生在这样的情况下：结果的月份里没有原来的月份的某天。 对于 ZF 的开发者来说，使用 extend_month 选项，当它为 false，就用 SQL 的方式，当它为 true，就用电子表格（如 Excel） 的方式。 extend_month 的缺省值为 false，和 SQL 方式兼容。 缺省地，Zend_Date 通过截取日期的月末部分（如果有必要）来计算月份，当原始日期指定这个月的某天超过结果月的天数时，不需要把它包含到下个月。 使用 Zend_Date::setOptions(array('extend_month' => true)); 使月份计算就像流行的电子表格程序（如 Excel）一样。

用 Zend_Cache 加速日期本地化和标准化

通过使用 Zend_Cache 适配器，你可以加速 Zend_Date 的运算。当你使用本地化的数据，Zend_Date 的所有方法都会加速。 例如所有接受 Zend_Date::DATE 和 Zend_Date::TIME 常量的方法将会从中受益。 用 Zend_Date::setOptions(array('cache' => $adapter)); 就可给 Zend_Date 设置一个 Zend_Cache 适配器。

用 Zend_TimeSync 同步时间戳

一般来说服务器和计算机上的时钟都不相同。Zend_TimeSync 帮助 Zend_Date 来处理这样的问题。 你可以用 Zend_Date::setOptions(array('timesync' => $timeserver)); 来设置一个时间服务器， 它将为所有 Zend_Date 的实例设置自己的实际时间戳和真实的实际时间戳之间的偏移量。使用这个选项不修改已存在的实例的时间戳。 最好的用法是在引导（bootstrap）文件里设置它。

使用日期值

一旦通过生成 Zend_Date 对象格式化输入，它就携带一个时区，但在内部用标准的 » UNIX 时间戳 来表示。 为了使日期能够本地化解析，必需知道时区。缺省的时区总是 GMT/UTC。用 getTimeZone()) 来检查对象的时区。 用 setTimeZone()) 来修改对象的时区。这些对象的所有处理都假定和这个时区相关。

要小心不同时区之间的对象的混合和日期部件的匹配操作，它可能会产生不期望的结果，除非运算只和时间戳相关。 除了上述的情况，Zend_Date 对象的操作会处理不同的时区，因为在 Zend_Date 初始化时日期被格式化成时间戳。

大部分方法需要一个常量来选择需要的日期的$part ，例如 Zend_Date::HOUR 。 这些常量对下面的所有函数有效，常数列表参见这里 所有常数列表 。 如果没有指定 $part，就使用 Zend_Date::TIMESTAMP。另外，也可以对 $part 使用用户指定的格式， 和 Zend_Locale_Format::getDate() 的基本机制和格式一样。 如果日期对象用明显的无效日期（如大于12的月份）来构造，那么 Zend_Date 将抛出异常，除非没有指定日期格式。例如， $part 是 null 或者 Zend_Date::DATES （"宽松" 格式） 。

Example #1 用户指定的日期输入格式

$date1 = new Zend_Date('Feb 31, 2007', null, 'en_US');
echo $date1, "\n"; // outputs "Mar 3, 2007 12:00:00 AM"

$date2 = new Zend_Date('Feb 31, 2007', Zend_Date::DATES, 'en_US');
echo $date2, "\n"; // outputs "Mar 3, 2007 12:00:00 AM"

// strictly restricts interpretation to specified format
$date3 = new Zend_Date('Feb 31, 2007', 'MM.dd.yyyy');
echo $date3, "\n"; // outputs "Mar 3, 2007 12:00:00 AM"

如果提供了可选的 $locale 参数，那么 $locale 通过给 $date 操作数替换月和星期名来消除它的歧义， 即使根据那个地方的约定来解析日期字符串 （参见 Zend_Locale_Format::getDate()）。 当 $part 是 Zend_Date::DATE* 或 Zend_Date::TIME* 常量其中之一，本地化的字符串类型的 $date 就自动格式化。 如果 $date 是包含日期的字符串，语言的地方标识符要用来解析月和星期的名字。 如果没有 $date 输入参数，那么 $locale 参数指定地方来用于本地化输出（例如，日期格式的字符串表示）。 注意 $date 输入参数可能实际有类型名 （例如 $hour 对于 addHour()），尽管它不能防止用 Zend_Date 对象作为参数。 如果没有指定 $locale ，那么当前对象的地方用于解释 $date，或选择本地化的格式来输出。

从 Zend Framework 1.7.0 开始，Zend_Date 也支持程序范围的地方的用法。你可以简单地如下设置 Zend_Locale 实例到注册表。 如果你想多次使用同一地方，用这个符号你不需要记住对每个实例手工设置地方。

// in your bootstrap file
$locale = new Zend_Locale('de_AT');
Zend_Registry::set('Zend_Locale', $locale);

// somewhere in your application
$date = new Zend_Date('31.Feb.2007');

Basic Zend_Date Operations Common to Many Date Parts

add(), sub(), compare(), get(), and set() 方法一般用来操作日期，就是操作对象里的日期。 除了 get()以外，$date 操作数对所有这些方法是必需的，它可能是 Zend_Date 实例对象、数字字符串或一个整数。 如果 $date 不是对象，这些方法就假定它是时间戳。然而，$part 操作数控制两个日期的逻辑部分，允许操作对象的日期的部件，如年或分钟， 即使 $date 包含一个长格式日期字符串，如 "December 31, 2007 23:59:59" 。 除了 compare() 和 get() 外，操作的结果是在对象里修改日期。

Example #2 日期部件的操作

$date = new Zend_Date(); // $date's timestamp === time()

// changes $date by adding 12 hours
$date->add('12', Zend_Date::HOUR);
print $date;

下表显示了基本操作的每个组合和若干普通的日期部件的方便方法。当使用上述一般的方法时，这些方便的方法帮助我们懒惰的程序员避免在 日期部件常量 方面的打字。 方便地，它们的名称由前缀（基本操作名）和后缀（日期部件类型）的组成，如 addYear() 。 在下面列表中，能看到所有“日期部件”和“基本操作”的组合。例如，"add"操作适用于这些日期部件，包括 addDay()、 addYear() 等。

这些方便的方法和基本操作方法有相同的功能，但期望字符串和整数的 $date 操作数只包含表示由方便方法的后缀指示的类型的值。 这样，当$date是字符串或整数时， 这些方法的名字（如"Year" 或 "Minute"）能确定 $date 操作数的单元。

日期部件列表

日期部件
日期部件 | 解释
» 时间戳 | UNIX 时间戳，表示从 January 1st, 1970 00:00:00 GMT/UTC 开始的秒数。
» 年 | 罗马教皇日历年（如 2006）
» 月 | 罗马教皇日历月（1-12, 支持本地化名字）
» 24 小时时钟 | 一天的小时数(0-23)，表示从一天开始算起过去的小时数。
» 分钟 | 一小时的分钟数(0-59)，表示从一小时开始算起过去的分钟数。
» 秒 | 一分钟的秒数(0-59)，表示从一分钟开始算起过去的秒数。
» 毫秒 | 毫秒表示千分之一秒(0-999)。Zend_Date 支持两个另外的方法来支持小于秒的时间单位。 缺省地，Zend_Date 实例精确到毫秒，如 getFractionalPrecision() ，我们用 setFractionalPrecision($precision) 来修改精确度。 然而，因为 Zend_Date 使用 » microtime()，精确度实际上限制到微秒。
» 天 | 如果 $date 操作数是 Zend_Date 的实例或一个数字字符串，Zend_Date::DAY_SHORT 是从 $date 里取出。 否则，根据这些文档 Zend_Date::WEEKDAY_NARROW、 Zend_Date::WEEKDAY_NAME、 Zend_Date::WEEKDAY_SHORT 和 Zend_Date::WEEKDAY （假定为罗马教皇日历）的惯例尝试从天里取出。
» 星期 | 如果 $date 操作数是 Zend_Date 的实例或一个数字字符串，Zend_Date::WEEK 是从 $date 里取出。 否则产生一个异常。（假定为罗马教皇日历）
日期 | 如果 $date 操作数是 Zend_Date 的实例或一个数字字符串，Zend_Date::DAY_MEDIUM 是从 $date 里取出。 否则就尝试格式化 $date 字符串成 Zend_Date::DATE_MEDIUM 日期格式。 Zend_Date::DAY_MEDIUM 格式根据地方的不同而不同。
Weekday | Weekdays 表示为从 0 （星期日） 到 6 （星期六）. 如果 $date 操作数是 Zend_Date 的实例或一个数字字符串，Zend_Date::WEEKDAY_DIGIT 是从 $date 里取出。 否则，根据这些文档 Zend_Date::WEEKDAY_NARROW、 Zend_Date::WEEKDAY_NAME、 Zend_Date::WEEKDAY_SHORT 和 Zend_Date::WEEKDAY （假定为罗马教皇日历）的惯例尝试从天里取出。
DayOfYear | 在 Zend_Date，一年中的天表示从一年开始发生的日历天数（0-365）。和其它上述单元一样，小数四舍五入到最近的整数。（假定为罗马教皇日历）
» Arpa | 我们支持 Arpa 日期（如 RFC 822 格式日期）。输出使用 "GMT" 或 "Local differential hours+min" 格式（见第5节的 RFC 822）。 在 PHP 5.2.2 以前，一起使用 DATE_RFC822 常量和 PHP 日期函数有时会产生 » 不正确的结果。 Zend_Date 的结果是正确的。例如 Mon, 31 Dec 06 23:59:59 GMT 。
» Iso | 对于输出只支持完全的 ISO 8601 日期。例如：2009-02-14T00:31:30+01:00

List of Date Operations 日期操作列表

如果 合适的常量 用于 $part 参数， 对特定日期部件，下列基本操作可用来代替方便操作。

基本操作
基本操作 | 解释
get() | get($part = null, $locale = null) 使用 get($part) 来获取这个对象的本地化到 $locale 为格式的字符串或整数的日期的 $part 。 当使用 BCMath 扩展，对大的值返回数字字符串而不是整数。 注: 不像 get()，其它 get*() 方便方法只返回 Zend_Date 的实例， 该实例包含一个表示选择的或计算的日期/时间的日期。
set() | set($date, $part = null, $locale = null) 对从带有 $locale 地方的输入 $date 找到的部件设置当前对象的 $part 一个相应的值。
add() | add($date, $part = null, $locale = null) 加上带有 $locale 地方的 $date 的 $part 到当前对象的日期。
sub() | sub($date, $part = null, $locale = null) 从当前对象的日期减去 加上带有 $locale 地方的 $date 的 $part 。
copyPart() | copyPart($part, $locale = null) 返回一个克隆的对象，只带有拷贝到克隆的对象的日期的 $part ，克隆带有它自己的地方任意地设置为 $locale （如果指定）。
compare() | compare($date, $part = null, $locale = null) 比较 $date 的 $part 和这个对象的时间戳，如果相等返回 0，如果对象部分更晚，返回1，否则返回 -1。

比较日期

对于列表在 Zend_Date API 概述的日期部件，下列基本操作没有相应的方便方法。

日期比较方法
方法 | 解释
equals() | equals($date, $part = null, $locale = null) 如果有 $locale 地方的 $date 的 $part 和这个对象的 $part 一样，返回 true，否则返回 false。
isEarlier() | isEarlier($date, $part = null, $locale = null) 如果对象的日期的 $part 早于 有 $locale 地方的 $date 的 $part ，返回 true。
isLater() | isLater($date, $part = null, $locale = null) 如果对象的日期的 $part 晚于有 $locale 地方的 $date 的 $part ，返回 true。
isToday() | isToday() 测试是否今天的年、月、日匹配这个对象的日期值，使用对象的时区。
isTomorrow() | isTomorrow() 测试是否明天的年、月、日匹配这个对象的日期值，使用对象的时区。
isYesterday() | isYesterday() 测试是否昨天的年、月、日匹配这个对象的日期值，使用对象的时区。
isLeapYear() | isLeapYear() 使用 isLeapYear() 来确定当前对象是否闰年，或使用 Zend_Date::checkLeapYear($year) 来 检查 $year，它可以是字符串、整数或 Zend_Date 的实例。这个年是闰年吗？
isDate() | isDate($date, $format = null, $locale = null) 这个方法检查给定的日期是否一个真实的日期并且如果所有检查通过返回 true。 它和 php 的 checkdate() 函数一样但也检查本地化月名和扩展了 checkdate() 范围的日期。

获取日期和日期部件

有若干方法支持获取和 Zend_Date 实例相关的值。

日期输出方法
方法 解释
toString()

toString($format = null, $locale = null)

直接调用或通过魔术方法 __toString() 。toString() 根据对象地方（或可选地指定 $locale）的约定 来自动格式化日期对象的值。支持的格式代码列表，参见 自定义 ISO 输出格式 。

toArray()

toArray()

根据对象的地方的约定返回选择的日期的表示的数组。返回数组和 PHP 的 » getdate() 函数相同并包括：

  • Number of day as 'day' (Zend_Date::DAY_SHORT)

  • Number of month as 'month' (Zend_Date::MONTH_SHORT)

  • Year as 'year' (Zend_Date::YEAR)

  • Hour as 'hour' (Zend_Date::HOUR_SHORT)

  • Minute as 'minute' (Zend_Date::MINUTE_SHORT)

  • Second as 'second' (Zend_Date::SECOND_SHORT)

  • Abbreviated timezone as 'timezone' (Zend_Date::TIMEZONE)

  • Unix timestamp as 'timestamp' (Zend_Date::TIMESTAMP)

  • Number of weekday as 'weekday' (Zend_Date::WEEKDAY_DIGIT)

  • Day of year as 'dayofyear' (Zend_Date::DAY_OF_YEAR)

  • Week as 'week' (Zend_Date::WEEK)

  • Delay of timezone to GMT as 'gmtsecs' (Zend_Date::GMT_SECS)

toValue()

toValue($part = null)

根据对象的地方的约定返回一个整数的选择的日期 $part 表示。
当 $part选择非数字值，如 Zend_Date::MONTH_NAME_SHORT ，返回 false。
注:这个方法调用 get()
并把结果做成 PHP 整数，如果  get() 返回一个包含对于你的系统的PHP太大的数的字符串，结果不可预计。
使用 get() 作为替换。
get()

get($part = null, $locale = null)

这个方法返回对象根据 $locale 本地化的日期的 $part，格式为字符串或整数。 更多信息参见List of Date Operations 日期操作列表。

now()

now($locale = null)

这个方便函数和 new Zend_Date() 相同。它以Zend_Date对象返回当前日期，有 $locale 。

使用秒的片段

Several methods support retrieving values related to a Zend_Date instance.

日期输出方法
方法 | 解释
getFractionalPrecision() | 返回秒的精度
setFractionalPrecision() | 设置秒的精度

日出 / 日落

有三个方法提供访问关于太阳的地理本地化信息，包括日出和日落的时间。

辅助方法
方法 | 解释
getSunrise($location) | 返回日期的日出时间
getSunset($location) | 返回日期的日落时间
getSunInfo($location) | 返回带有日期的太阳日期的数组
基本方法
Zend_Date
Zend Framework手册 中文版
生成日期
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Date
  • 简介
  • 操作理论
  • 基本方法
  • Zend_Date API 概述
  • 生成日期
  • 一般日期函数的常量
  • Working 范例


生成日期 - Zend Framework Manual

Zend_Date API 概述
Zend_Date
Zend Framework手册 中文版
一般日期函数的常量

生成日期

因为需求的不同，Zend_Date 提供了若干不同的办法来创建自己的实例，本章将介绍最方便的办法。

生成当前日期

最简单的创建日期对象是生成当前的日期，通过创建new Zend_Date()的实例 或使用静态方法 Zend_Date::now() 都可以，它们都返回当前日期的 Zend_Date 实例。 当前的日期总是包括当前的日期和时间以及当前的时区。

Example #1 通过实例生成日期

通过创建一个新的实例来生成日期意味着你不需要给出参数。当然有若干个参数我们将以后来描述，但一般 来说这是最简单和最常用的方法来获得当期日期为 Zend_Date 的实例。

$date = new Zend_Date();

Example #2 静态日期生成

有时候用静态方法生成日期更容易。因此，你可以使用 now() 方法， 它返回 Zend_Date 的一个新实例，就象你用 new Zend_Date() 一样。 但它将总返回当前日期并且不能用可选的参数修改。

$date = Zend_Date::now();

从数据库生成日期

数据库常用来存储数据。问题是，每个数据库用不同的方式输出数据。MsSQL 数据库和 MySQL 数据库的日期标准就不一样。为简化起见，Zend_Date 可以很容易从数据库数据生成日期。

当然每个数据库都可以说把输出转换成定义好的特殊值。例如，你可以把 datetime 转换成输出分钟值。 但这很耗时并且当查询数据库时你确实需要用其它方法来处理日期。

所以我们有一个快速并方便的方法从数据库值生成日期。

Example #3 快速从数据库生成日期

众所周知，所有的数据库都想尽可能快地查询数据，它们与生俱来就要快速响应。从数据库取得日期的最快 方法是使用unix时间戳。所有数据库在内部把日期值都存成时间戳（不是unix时间戳）。这意味着通过查询生 成时间戳要比转换成其它格式快。

// SELECT UNIX_TIMESTAMP(my_datetime_column) FROM my_table
$date = new Zend_Date($unixtimestamp, Zend_Date::TIMESTAMP);

Example #4 从数据库方便地生成日期

即使是你乍一看它们都相同，但是所有数据库的标准输出还是不一样的。但它们都是 ISO 标准的一部分 并解释它，所以最容易的生成日期的方法是使用 Zend_Date::ISO_8601。 例如数据库里众所周知的 MySQL 和 MsSQL 被 Zend_Date::ISO_8601 认可。 但所有数据库也都可以返回一个 ISO 8601 表示的日期列。 ISO 8601 一个巨大的有点是人类可读。缺点是 ISO 8601 比 unix 时间戳需要更多 的时间来处理，但也应该知道 unix 时间戳只支持 1970年1月1日以后的日期。

// SELECT datecolumn FROM my_table
$date = new Zend_Date($datecolumn, Zend_Date::ISO_8601);

从数组生成日期

日期也可以从数组生成，这是个简单并容易的方法，使用的数组键是：

  • 日: 日期的天数

  • 月: 日期的月数

  • 年: full year of the date

  • 小时: 小时数

  • 分钟: 分钟数

  • 秒: 秒数

Example #5 通过数组生成日期

一般地你需要给出一个完整的日期数组用于新的日期实例的生成，但当你没有给出所有值，未给出的值就是零。 这意味着如果没有给出小时值，那么就用 0 小时。

$datearray = array('year' => 2006,
                   'month' => 4,
                   'day' => 18,
                   'hour' => 12,
                   'minute' => 3,
                   'second' => 10);
$date = new Zend_Date($datearray);

$datearray = array('year' => 2006, 'month' => 4, 'day' => 18);
$date = new Zend_Date($datearray);
Zend_Date API 概述
Zend_Date
Zend Framework手册 中文版
一般日期函数的常量
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Date
  • 简介
  • 操作理论
  • 基本方法
  • Zend_Date API 概述
  • 生成日期
  • 一般日期函数的常量
  • Working 范例


一般日期函数的常量 - Zend Framework Manual

生成日期
Zend_Date
Zend Framework手册 中文版
Working 范例

一般日期函数的常量

不论什么时候 Zend_Date 方法需要参数 $parts，下面常数中其中之一可担当此任， 用来选择日期的特定部分或指示日期使用的或期望使用的格式（例如 RFC 822）。

使用常数

例如，常数 Zend_Date::HOUR 可以像下列所示来使用。当和星期几、日期、小时、分钟、秒和任何其它因位于世界不同的地方而不同地表示的日期部分一起使用时， 对象的时区将自动用来计算当前值，即使是内部的时间戳和此刻一致并且不论用户的地理位置在世界的何方。 不管使用了哪些单元，输出必需表达为 GMT/UTC 或本地化。下面的输出例子反映了 Europe/GMT+1 hour (e.g. Germany, Austria, France) 的本地化。

Zend_Date::HOUR 的操作
函数/输入 | 描述 | 原始日期 | 效果/输出
get(Zend_Date::HOUR) | Output of the hour | 2009-02-13T14:53:27+01:00 | 14
set(12, Zend_Date::HOUR) | Set new hour | 2009-02-13T14:53:27+01:00 | 2009-02-13T12:53:27+01:00
add(12, Zend_Date::HOUR) | Add hours | 2009-02-13T14:53:27+01:00 | 2009-02-14T02:53:27+01:00
sub(12, Zend_Date::HOUR) | Subtract hours | 2009-02-13T14:53:27+01:00 | 2009-02-13T02:53:27+01:00
compare(12, Zend_Date::HOUR) | Compare hour, returns 0, 1 or -1 | 2009-02-13T14:53:27+01:00 | 1 (if object > argument)
copy(Zend_Date::HOUR) | Copies only the hour part | 2009-02-13T14:53:27+01:00 | 1970-01-01T14:00:00+01:00
equals(14, Zend_Date::HOUR) | Compares the hour, returns TRUE or FALSE | 2009-02-13T14:53:27+01:00 | TRUE
isEarlier(12, Zend_Date::HOUR) | Compares the hour, returns TRUE or FALSE | 2009-02-13T14:53:27+01:00 | TRUE
isLater(12, Zend_Date::HOUR) | Compares the hour, returns TRUE or FALSE | 2009-02-13T14:53:27+01:00 | FALSE

所有常数列表

在 Zend_Date 中每个日期/时间的部分都有独一无二的常数。所有 Zend_Date 支持的常数如下：

Day Constants
常数 | 描述 | 日期 | 受影响部分/例子
Zend_Date::DAY | Day (as a number, two digit) | 2009-02-06T14:53:27+01:00 | 2009-02-06T14:53:27+01:00 (06)
Zend_Date::DAY_SHORT | Day (as a number, one or two digit) | 2009-02-06T14:53:27+01:00 | 2009-02-06T14:53:27+01:00 (6)
Zend_Date::WEEKDAY | Weekday (Name of the day, localized, complete) | 2009-02-06T14:53:27+01:00 | Friday
Zend_Date::WEEKDAY_SHORT | Weekday (Name of the day, localized, abbreviated, the first three digits) | 2009-02-06T14:53:27+01:00 | Fre for Friday
Zend_Date::WEEKDAY_NAME | Weekday (Name of the day, localized, abbreviated, the first two digits) | 2009-02-06T14:53:27+01:00 | Fr for Friday
Zend_Date::WEEKDAY_NARROW | Weekday (Name of the day, localized, abbreviated, only the first digit) | 2009-02-06T14:53:27+01:00 | F for Friday
Zend_Date::WEEKDAY_DIGIT | Weekday (0 = Sunday, 6 = Saturday) | 2009-02-06T14:53:27+01:00 | 5 for Friday
Zend_Date::WEEKDAY_8601 | Weekday according to ISO 8601 (1 = Monday, 7 = Sunday) | 2009-02-06T14:53:27+01:00 | 5 for Friday
Zend_Date::DAY_OF_YEAR | Day (as a number, one or two digit) | 2009-02-06T14:53:27+01:00 | 43
Zend_Date::DAY_SUFFIX | English addendum for the day (st, nd, rd, th) | 2009-02-06T14:53:27+01:00 | th
星期常数
常数 | 描述 | 日期 | 受影响部分/例子
Zend_Date::WEEK | Week (as a number, 1-53) | 2009-02-06T14:53:27+01:00 | 7
月常数
常数 | 描述 | 日期 | 受影响部分/例子
Zend_Date::MONTH_NAME | Month (Name of the month, localized, complete) | 2009-02-06T14:53:27+01:00 | February
Zend_Date::MONTH_NAME_SHORT | Month (Name of the month, localized, abbreviated, three digit) | 2009-02-06T14:53:27+01:00 | Feb
Zend_Date::MONTH_NAME_NARROW | Month (Name of the month, localized, abbreviated, one digit) | 2009-02-06T14:53:27+01:00 | F
Zend_Date::MONTH | Month (Number of the month, two digit) | 2009-02-06T14:53:27+01:00 | 2009-02-06T14:53:27+01:00 (02)
Zend_Date::MONTH_SHORT | Month (Number of the month, one or two digit) | 2009-02-06T14:53:27+01:00 | 2009-02-06T14:53:27+01:00 (2)
Zend_Date::MONTH_DAYS | Number of days for this month (number) | 2009-02-06T14:53:27+01:00 | 28
年常数
常数 | 描述 | 日期 | 受影响部分/例子
Zend_Date::YEAR | Year (number) | 2009-02-06T14:53:27+01:00 | 2009-02-06T14:53:27+01:00
Zend_Date::YEAR_8601 | Year according to ISO 8601 (number) | 2009-02-06T14:53:27+01:00 | 2009
Zend_Date::YEAR_SHORT | Year (number, two digit) | 2009-02-06T14:53:27+01:00 | 2009-02-06T14:53:27+01:00
Zend_Date::YEAR_SHORT_8601 | Year according to ISO 8601 (number, two digit) | 2009-02-06T14:53:27+01:00 | 09
Zend_Date::LEAPYEAR | Is the year a leap year? (TRUE or FALSE) | 2009-02-06T14:53:27+01:00 | FALSE
时间常数
常数 | 描述 | 日期 | 受影响部分/例子
Zend_Date::HOUR | Hour (00-23, two digit) | 2009-02-06T14:53:27+01:00 | 14
Zend_Date::HOUR_SHORT | Hour (0-23, one or two digit) | 2009-02-06T14:53:27+01:00 | 14
Zend_Date::HOUR_SHORT_AM | Hour (1-12, one or two digit) | 2009-02-06T14:53:27+01:00 | 2
Zend_Date::HOUR_AM | Hour (01-12, two digit) | 2009-02-06T14:53:27+01:00 | 02
Zend_Date::MINUTE | Minute (00-59, two digit) | 2009-02-06T14:53:27+01:00 | 2009-02-06T14:53:27+01:00
Zend_Date::MINUTE_SHORT | Minute (0-59, one or two digit) | 2009-02-06T14:03:27+01:00 | 2009-02-06T14:03:27+01:00
Zend_Date::SECOND | Second (00-59, two digit) | 2009-02-06T14:53:27+01:00 | 2009-02-06T14:53:27+01:00
Zend_Date::SECOND_SHORT | Second (0-59, one or two digit) | 2009-02-06T14:53:07+01:00 | 2009-02-06T14:53:07+01:00
Zend_Date::MILLISECOND | Millisecond (theoretically infinite) | 2009-02-06T14:53:27.20546 | 2009-02-06T14:53:27.20546
Zend_Date::MERIDIEM | Time of day (forenoon/afternoon) | 2009-02-06T14:53:27+01:00 | afternoon
Zend_Date::SWATCH | Swatch Internet Time | 2009-02-06T14:53:27+01:00 | 620
时区常数
常数 | 描述 | 日期 | 受影响部分/例子
Zend_Date::TIMEZONE | Name der time zone (string, abbreviated) | 2009-02-06T14:53:27+01:00 | CET
Zend_Date::TIMEZONE_NAME | Name of the time zone (string, complete) | 2009-02-06T14:53:27+01:00 | Europe/Paris
Zend_Date::TIMEZONE_SECS | Difference of the time zone to GMT in seconds (integer) | 2009-02-06T14:53:27+01:00 | 3600 seconds to GMT
Zend_Date::GMT_DIFF | Difference to GMT in seconds (string) | 2009-02-06T14:53:27+01:00 | +0100
Zend_Date::GMT_DIFF_SEP | Difference to GMT in seconds (string, separated) | 2009-02-06T14:53:27+01:00 | +01:00
Zend_Date::DAYLIGHT | Summer time or Winter time? (TRUE or FALSE) | 2009-02-06T14:53:27+01:00 | FALSE
日期格式常数（格式包括时区）
常数 | 描述 | 日期 | 受影响部分/例子
Zend_Date::ISO_8601 | Date according to ISO 8601 (string, complete) | 2009-02-13T14:53:27+01:00 | 2009-02-13T14:53:27+01:00
Zend_Date::RFC_2822 | Date according to RFC 2822 (string) | 2009-02-13T14:53:27+01:00 | Fri, 13 Feb 2009 14:53:27 +0100
Zend_Date::TIMESTAMP | » Unix time (seconds since 1.1.1970, mixed) | 2009-02-13T14:53:27+01:00 | 1234533207
Zend_Date::ATOM | Date according to ATOM (string) | 2009-02-13T14:53:27+01:00 | 2009-02-13T14:53:27+01:00
Zend_Date::COOKIE | Date for Cookies (string, for Cookies) | 2009-02-13T14:53:27+01:00 | Friday, 13-Feb-09 14:53:27 Europe/Paris
Zend_Date::RFC_822 | Date according to RFC 822 (string) | 2009-02-13T14:53:27+01:00 | Fri, 13 Feb 09 14:53:27 +0100
Zend_Date::RFC_850 | Date according to RFC 850 (string) | 2009-02-13T14:53:27+01:00 | Friday, 13-Feb-09 14:53:27 Europe/Paris
Zend_Date::RFC_1036 | Date according to RFC 1036 (string) | 2009-02-13T14:53:27+01:00 | Fri, 13 Feb 09 14:53:27 +0100
Zend_Date::RFC_1123 | Date according to RFC 1123 (string) | 2009-02-13T14:53:27+01:00 | Fri, 13 Feb 2009 14:53:27 +0100
Zend_Date::RSS | Date for RSS Feeds (string) | 2009-02-13T14:53:27+01:00 | Fri, 13 Feb 2009 14:53:27 +0100
Zend_Date::W3C | Date for HTML/HTTP according to W3C (string) | 2009-02-13T14:53:27+01:00 | 2009-02-13T14:53:27+01:00

特别注意 Zend_Date::DATES，因为这个格式指示器在 Zend_Date 之内有个唯一的属性作为 输入 格式指示器。 当 $part 用作一个输入格式，该常量提灵活地接受许多相似的日期格式。启发式自动从输入字符串里解析并“修改”日期里的简单的错误（如果有的话），如当需要时，交换年月日的位置。

日期和时间格式 (format varies by locale)
常数 | 描述 | 日期 | 受影响部分/例子
Zend_Date::ERA | Epoch (string, localized, abbreviated) | 2009-02-06T14:53:27+01:00 | AD (anno Domini)
Zend_Date::ERA_NAME | Epoch (string, localized, complete) | 2009-02-06T14:53:27+01:00 | anno domini (anno Domini)
Zend_Date::DATES | Standard date (string, localized, default value). | 2009-02-13T14:53:27+01:00 | 13.02.2009
Zend_Date::DATE_FULL | Complete date (string, localized, complete) | 2009-02-13T14:53:27+01:00 | Friday, 13. February 2009
Zend_Date::DATE_LONG | Long date (string, localized, long) | 2009-02-13T14:53:27+01:00 | 13. February 2009
Zend_Date::DATE_MEDIUM | Normal date (string, localized, normal) | 2009-02-13T14:53:27+01:00 | 13.02.2009
Zend_Date::DATE_SHORT | Abbreviated Date (string, localized, abbreviated) | 2009-02-13T14:53:27+01:00 | 13.02.09
Zend_Date::TIMES | Standard time (string, localized, default value) | 2009-02-13T14:53:27+01:00 | 14:53:27
Zend_Date::TIME_FULL | Complete time (string, localized, complete) | 2009-02-13T14:53:27+01:00 | 14:53 Uhr CET
Zend_Date::TIME_LONG | Long time (string, localized, Long) | 2009-02-13T14:53:27+01:00 | 14:53:27 CET
Zend_Date::TIME_MEDIUM | Normal time (string, localized, normal) | 2009-02-13T14:53:27+01:00 | 14:53:27
Zend_Date::TIME_SHORT | Abbreviated time (string, localized, abbreviated) | 2009-02-13T14:53:27+01:00 | 14:53

自定义 ISO 输出格式

如果你需要的日期格式没有在上述的格式中出现，那么使用从下面 ISO 格式指定器产生的自定义格式。 下面的例子示例了从下列表中生成的自定义 ISO 格式的常量的用法。格式长度无限制。并且允许格式常量的多重用法。

如果你喜欢的话，可接受的格式指定器可以从 ISO 格式修改为 PHP 的日期格式，然而，PHP 日期格式指定不支持所有的按 ISO 标准定义的格式。 使用 Zend_Date::setOptions(array('format_type' => 'php')) 方法来把 Zend_Date 方法从支持 ISO 格式制定器切换到 PHP date()类型制定器（参见下面 使用 PHP 的 date() 格式指定器的自定义输出格式）。

Example #1 自定义 ISO 格式用法示例

$locale = new Zend_Locale('de_AT');
$date = new Zend_Date(1234567890, false, $locale);
print $date->toString("'Era:GGGG='GGGG, ' Date:yy.MMMM.dd'yy.MMMM.dd");

ISO 8601 日期输出 常量
常数 | 描述 | 日期 | 受影响部分/例子
G | Epoch, localized, abbreviated | Zend_Date::ERA | AD
GG | Epoch, localized, abbreviated | Zend_Date::ERA | AD
GGG | Epoch, localized, abbreviated | Zend_Date::ERA | AD
GGGG | Epoch, localized, complete | Zend_Date::ERA_NAME | anno domini
GGGGG | Epoch, localized, abbreviated | Zend_Date::ERA | a
y | Year, at least one digit | Zend_Date::YEAR | 9
yy | Year, at least two digit | Zend_Date::YEAR_SHORT | 09
yyy | Year, at least three digit | Zend_Date::YEAR | 2009
yyyy | Year, at least four digit | Zend_Date::YEAR | 2009
yyyyy | Year, at least five digit | Zend_Date::YEAR | 02009
Y | Year according to ISO 8601, at least one digit | Zend_Date::YEAR_8601 | 9
YY | Year according to ISO 8601, at least two digit | Zend_Date::YEAR_SHORT_8601 | 09
YYY | Year according to ISO 8601, at least three digit | Zend_Date::YEAR_8601 | 2009
YYYY | Year according to ISO 8601, at least four digit | Zend_Date::YEAR_8601 | 2009
YYYYY | Year according to ISO 8601, at least five digit | Zend_Date::YEAR_8601 | 02009
M | Month, one or two digit | Zend_Date::MONTH_SHORT | 2
MM | Month, two digit | Zend_Date::MONTH | 02
MMM | Month, localized, abbreviated | Zend_Date::MONTH_NAME_SHORT | Feb
MMMM | Month, localized, complete | Zend_Date::MONTH_NAME | February
MMMMM | Month, localized, abbreviated, one digit | Zend_Date::MONTH_NAME_NARROW | F
w | Week, one or two digit | Zend_Date::WEEK | 5
ww | Week, two digit | Zend_Date::WEEK | 05
d | Day of the month, one or two digit | Zend_Date::DAY_SHORT | 9
dd | Day of the month, two digit | Zend_Date::DAY | 09
D | Day of the year, one, two or three digit | Zend_Date::DAY_OF_YEAR | 7
DD | Day of the year, two or three digit | Zend_Date::DAY_OF_YEAR | 07
DDD | Day of the year, three digit | Zend_Date::DAY_OF_YEAR | 007
E | Day of the week, localized, abbreviated, one char | Zend_Date::WEEKDAY_NARROW | M
EE | Day of the week, localized, abbreviated, two char | Zend_Date::WEEKDAY_NAME | Mo
EEE | Day of the week, localized, abbreviated, three char | Zend_Date::WEEKDAY_SHORT | Mon
EEEE | Day of the week, localized, complete | Zend_Date::WEEKDAY | Monday
EEEEE | Day of the week, localized, abbreviated, one digit | Zend_Date::WEEKDAY_NARROW | M
e | Number of the day, one digit | Zend_Date::WEEKDAY_NARROW | 4
ee | Number of the day, two digit | Zend_Date::WEEKDAY_NARROW | 04
a | Time of day, localized | Zend_Date::MERIDIEM | vorm.
h | Hour, (1-12), one or two digit | Zend_Date::HOUR_SHORT_AM | 2
hh | Hour, (01-12), two digit | Zend_Date::HOUR_AM | 02
H | Hour, (0-23), one or two digit | Zend_Date::HOUR_SHORT | 2
HH | Hour, (00-23), two digit | Zend_Date::HOUR | 02
m | Minute, (0-59), one or two digit | Zend_Date::MINUTE_SHORT | 2
mm | Minute, (00-59), two digit | Zend_Date::MINUTE | 02
s | Second, (0-59), one or two digit | Zend_Date::SECOND_SHORT | 2
ss | Second, (00-59), two digit | Zend_Date::SECOND | 02
S | Millisecond | Zend_Date::MILLISECOND | 20536
z | Time zone, localized, abbreviated | Zend_Date::TIMEZONE | CET
zz | Time zone, localized, abbreviated | Zend_Date::TIMEZONE | CET
zzz | Time zone, localized, abbreviated | Zend_Date::TIMEZONE | CET
zzzz | Time zone, localized, complete | Zend_Date::TIMEZONE_NAME | Europe/Paris
Z | Difference of time zone | Zend_Date::GMT_DIFF | +0100
ZZ | Difference of time zone | Zend_Date::GMT_DIFF | +0100
ZZZ | Difference of time zone | Zend_Date::GMT_DIFF | +0100
ZZZZ | Difference of time zone, separated | Zend_Date::GMT_DIFF_SEP | +01:00
A | Millisecond | Zend_Date::MILLISECOND | 20563

Note: 注意缺省的 ISO 格式不同于 PHP 的格式，如果在先前没有使用，PHP 的格式可以迭代。 特别是 Year and Minute 的格式指定器不常按预期来使用。
对于 year 有两个可用的指定器经常发生错误： ISO 年的Y 指定器和真实年的 y 的指定器。 区别微小但意义重大。 Y 计算 ISO 年，常用于日历格式，例如 the 31. December 2007。 真实年为 2007，但它是 2008 年的第一周的第一天，所以，如果使用 'dd.MM.yyyy' 会得到 '31.December.2007' 但如果使用 'dd.MM.YYYY' 会得到 '31.December.2008'。 正如你所看到的，这不是 bug ， 但期望的行为依赖指定器的使用。
对 minute 来说区别不大。ISO 使用 m 指定器，PHP 使用 i。 所以如果没有按你的格式获得分钟数，检查是否使用了正确的指定器。

使用 PHP 的 date() 格式指定器的自定义输出格式

如果你更喜欢使用 PHP 的日期格式指定器，可以使用 Zend_Date::setOptions(array('format' => 'php')) 方法 把 Zend_Date 方法从支持 ISO 格式制定器切换到 PHP date()类型制定器。然后所有参数必需用 » PHP's date() 格式指定器 给出。 PHP 日期格式缺乏一些 ISO 格式支持的格式，反之亦然。如果不喜欢，可以使用标准的 ISO 格式。 而且，如果你有一些历史遗留的使用 PHP 日期格式的代码，可以用 Zend_Locale_Format::convertPhpToIsoFormat() 手工转换为 ISO 格式，或使用 setOptions()。 下面的例子示例了从下表生成的自定义格式的常量的用法。

Example #2 用 PHP 指定器自定义格式的用例

$locale = new Zend_Locale('de_AT');
Zend_Date::setOptions(array('format_type' => 'php'));
$date = new Zend_Date(1234567890, false, $locale);

// outputs something like 'February 16, 2007, 3:36 am'
print $date->toString('F j, Y, g:i a');

print $date->toString("'Format:D M j G:i:s T Y='D M j G:i:s T Y");

下标列出了带有相应等同的 Zend_Date常量和 CLDR/ISO 格式指定器的 PHP 日期格式指定器。 对一些情况，当 CLDR/ISO 格式没有等同的格式指定器时，PHP 格式指定器不用 Zend_Locale_Format::convertPhpToIsoFormat() 来改变， 并且 Zend_Date 方法承认这些 “奇特的” PHP 格式指定器，即使是处于缺省的 "ISO" 格式模式中。

PHP 日期输出 常量
常数 | 描述 | Corresponds best to | closest CLDR equivalent | 受影响部分/例子
d | Day of the month, two digit | Zend_Date::DAY | dd | 09
D | Day of the week, localized, abbreviated, three digit | Zend_Date::WEEKDAY_SHORT | EEE | Mon
j | Day of the month, one or two digit | Zend_Date::DAY_SHORT | d | 9
l (lowercase L) | Day of the week, localized, complete | Zend_Date::WEEKDAY | EEEE | Monday
N | Number of the weekday, one digit | Zend_Date::WEEKDAY_8601 | e | 4
S | English suffixes for day of month, two chars | no equivalent | no equivalent | st
w | Number of the weekday, 0=sunday, 6=saturday | Zend_Date::WEEKDAY_DIGIT | no equivalent | 4
z | Day of the year, one, two or three digit | Zend_Date::DAY_OF_YEAR | D | 7
W | Week, one or two digit | Zend_Date::WEEK | w | 5
F | Month, localized, complete | Zend_Date::MONTH_NAME | MMMM | February
m | Month, two digit | Zend_Date::MONTH | MM | 02
M | Month, localized, abbreviated | Zend_Date::MONTH_NAME_SHORT | MMM | Feb
n | Month, one or two digit | Zend_Date::MONTH_SHORT | M | 2
t | Number of days per month, one or two digits | Zend_Date::MONTH_DAYS | no equivalent | 30
L | Leapyear, boolean | Zend_Date::LEAPYEAR | no equivalent | true
o | Year according to ISO 8601, at least four digit | Zend_Date::YEAR_8601 | YYYY | 2009
Y | Year, at least four digit | Zend_Date::YEAR | yyyy | 2009
y | Year, at least two digit | Zend_Date::YEAR_SHORT | yy | 09
a | Time of day, localized | Zend_Date::MERIDIEM | a (sort of, but likely to be uppercase) | vorm.
A | Time of day, localized | Zend_Date::MERIDIEM | a (sort of, but no guarantee that the format is uppercase) | VORM.
B | Swatch internet time | Zend_Date::SWATCH | no equivalent | 1463
g | Hour, (1-12), one or two digit | Zend_Date::HOUR_SHORT_AM | h | 2
G | Hour, (0-23), one or two digit | Zend_Date::HOUR_SHORT | H | 2
h | Hour, (01-12), two digit | Zend_Date::HOUR_AM | hh | 02
H | Hour, (00-23), two digit | Zend_Date::HOUR | HH | 02
i | Minute, (00-59), two digit | Zend_Date::MINUTE | mm | 02
s | Second, (00-59), two digit | Zend_Date::SECOND | ss | 02
e | Time zone, localized, complete | Zend_Date::TIMEZONE_NAME | zzzz | Europe/Paris
I | Daylight | Zend_Date::DAYLIGHT | no equivalent | 1
O | Difference of time zone | Zend_Date::GMT_DIFF | Z or ZZ or ZZZ | +0100
P | Difference of time zone, separated | Zend_Date::GMT_DIFF_SEP | ZZZZ | +01:00
T | Time zone, localized, abbreviated | Zend_Date::TIMEZONE | z or zz or zzz | CET
Z | Time zone offset in seconds | Zend_Date::TIMEZONE_SECS | no equivalent | 3600
c | Standard Iso format output | Zend_Date::ISO_8601 | no equivalent | 2004-02-12T15:19:21+00:00
r | Standard Rfc 2822 format output | Zend_Date::RFC_2822 | no equivalent | Thu, 21 Dec 2000 16:01:07 +0200
U | Unix timestamp | Zend_Date::TIMESTAMP | no equivalent | 15275422364
生成日期
Zend_Date
Zend Framework手册 中文版
Working 范例
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Date
  • 简介
  • 操作理论
  • 基本方法
  • Zend_Date API 概述
  • 生成日期
  • 一般日期函数的常量
  • Working 范例


Working 范例 - Zend Framework Manual

一般日期函数的常量
Zend_Date
Zend Framework手册 中文版
Zend_Db

Working 范例

在本章内，我们将描述若干附加的函数，它们在 Zend_Date 中也有效。 当然所述的函数有另外的范例来示范期望的工作和简单的如何正确使用的 API 。

检查日期

大部分输入的日期可能是字符串，问题是你不能确保这些字符串是真的日期。因此 Zend_Date 有个特有的静态函数来加查日期字符串。Zend_Locale 有个特有的函数 getDate($date, $locale); ，它解析 日期并返回正确的格式化的日期部分。例如月名将被识别和返回月数。 但 Zend_Locale 不知道什么是日期，因为它是个格式化和本地化的类，所以我们集成了一个特有的函数 isDate($date); 来做这个。

isDate($date, $format, $locale); 最多可以带 3 个参数但最少需要一个参数。所以我们需要校验的日期当然是它本身是否一个字符串。 第二个参数是日期的格式。如果没有给定格式，使用地方的标准格式。关于格式的细节参见 自定义格式 。

第三个参数也是可选的并可用于给定一个地方。我们需要地方来格式化月名和天名（monthnames and daynames）。 所以用第三个参数我们可以根据给定的地方识别 '01.Jänner.2000' 或 '01.January.2000'这样的日期。

isDate(); 当然来检查是否一个日期存在。Zend_Date自己不检查日期。 所以有可能用 Zend_Date 生成一个如 '31.February.2000'的日期，因为 Zend_Date 将 自动纠正日期并返回适当的日期，在这个例子中为 '03.March.2000' 。而 isDate() 将检查并对 '31.February.2000' 返回 false， 因为它知道这是个不可能的日期。

Example #1 检查日期

// Checking dates
$date = '01.03.2000';
if (Zend_Date::isDate($date)) {
    print "String $date is a date";
} else {
    print "String $date is NO date";
}

// Checking localized dates
$date = '01 February 2000';
if (Zend_Date::isDate($date,'dd MMMM yyyy', 'en')) {
    print "String $date is a date";
} else {
    print "String $date is NO date";
}

// Checking impossible dates
$date = '30 February 2000';
if (Zend_Date::isDate($date,'dd MMMM yyyy', 'en')) {
    print "String $date is a date";
} else {
    print "String $date is NO date";
}

日出和日落

Zend_Date 也集成了从太阳获得信息的功能。通常在一个特定的日子里获得日出和日落的时间是有必要的。 用Zend_Date 来做很容易，因为仅仅给定位置就可以计算到日出日落的时间。

正如很多人不知道他们所居住的城市的位置，我们也使用助手类来提供了世界上大约 250个首都和其它大城市的位置数据。 大多数人使用他们附近的城市来作为地方，这样计算上会差一点时间。

用 Zend_Date_Cities::getCityList 可以生成一个列表来选择城市。它返回所有在助手类中预定义的可用的城市名称。

Example #2 获得所有可用的城市

// Output the complete list of available cities
print_r (Zend_Date_Cities::getCityList());

用 Zend_Date_Cities::City() 函数可以获得位置。它接受由 Zend_Date_Cities::getCityList() 函数返回的城市名 和可选的第二个参数来设置地平线（horizon）.

'effective' horizon is used. 有 4 个已定义的地平线可用于位置类精确计算日落和日出。'horizon' 参数在所有的函数中总是可选的。 如果没有指定，则使用 'effective' 。

日落和日出支持的地平线（horizons）类型
地平线（Horizon） | 描述 | 用法
effective | 标准地平线 | 认为世界是一个球。这个地平线是缺省值
civil | 通用地平线 | 常用于媒体如电视和电台
nautic | 水兵地平线 | 常用于大海导航
astronomic | 天文学地平线 | 常用于星际计算

当然也可以给出和计算自定义位置，因此 'latitude' 和 'longitude' 必需给定，而 'horizon' 是可选的。

Example #3 获得一个城市的位置

// Get the location for a defined city
// uses the effective horizon as no horizon is defined
print_r (Zend_Date_Cities::City('Vienna'));

// use the nautic horizon
print_r (Zend_Date_Cities::City('Vienna', 'nautic'));

// self definition of a location
$mylocation = array('latitude' => 41.5, 'longitude' => 13.2446);

现在所有需要的数据可以被设置了，下一步是创建带有计算日落和日出的日期的 Zend_Date 对象。 有三个函数用于计算，用 'getSunset()' 计算日落，用 'getSunrise()' 计算日出，所有和太阳相关的信息使用 'getSunInfo()' 。 经过计算后，Zend_Date 对象返回时就带有计算过的时间。

Example #4 计算太阳信息

// Get the location for a defined city
$city = Zend_Date_Cities::City('Vienna');

// create a date object for the day for which the sun has to be calculated
$date = new Zend_Date('10.03.2007', Zend_Date::ISO_8601, 'de');

// calculate sunset
$sunset = $date->getSunset($city);
print $sunset->get(Zend_Date::ISO_8601);

// calculate all sun informations
$info = $date->getSunInfo($city);
foreach ($info as $sun) {
    print "\n" . $sun->get(Zend_Date::ISO_8601);
}

时区

时区和日期一样重要，根据用户所居住的地方，有若干时区，所以使用日期意味着要正确设置时区。 这听起来很复杂但其实比较简单。正如在 Zend_Date 的第一章所提到的，缺省的时区已经通过 php.ini 或在引导文件（bootstrap file）里定义来设置，

Zend_Date 对象当然也存储实际的时区。即使在对象创建后修改时区，它也能记住原来的时区并使用它。 也不必要在使用php函数的代码里修改时区，Zend_Date 有两个内置的函数来处理这个。

getTimezone() 返回实际的在 Zend_Date 对象里的时区。请记住 Zend_Date 在内部不和 php 耦合， 返回的时区不是 php 脚本的时区二是对象的时区。 setTimezone($zone) 是第二个函数并为 Zend_Date 设置新时区。给定的时区总是被检查的，如果不存在就抛出异常。 另外通过不带区域参数调用 setTimezone() 实际脚本或系统时区可以被设置到日期对象，在对象被创建是这个也会自动完成。

Example #5 使用时区

// Set a default timezone... this has to be done within the bootstrap
// file or php.ini
// We do this here just for having a complete example
date_default_timezone_set('Europe/Vienna');

// create a date object
$date = new Zend_Date('10.03.2007', Zend_Date::DATES, 'de');

// view our date object
print $date->getIso();

// what timezone do we have ?
print $date->getTimezone();

// set another timezone
$date->setTimezone('America/Chicago');

// what timezone do we now have ?
print $date->getTimezone();

// see the changed date object
print $date->getIso();

如上面例子的第一行所示，Zend_Date 对创建对象总是使用实际的时区。在被创建的对象里修改时区 对日期自己有影响。日期总是和时区相关。对 Zend_Date 对象修改时区不会修改 Zend_Date 的时间。 请记住在内部日期总是以时间戳和 GMT 时区存储。所以时区就意味者对用户所在时区和地区对实际的国际时间的加减。

在 Zend_Date 里耦合时区有另一个正面影响，在不同的时区有可能有若干个日期。

Example #6 多重时区

// Set a default timezone... this has to be done within the bootstrap
// file or php.ini.
// We do this here just for having a complete example.
date_default_timezone_set('Europe/Vienna');

// create a date object
$date = new Zend_Date('10.03.2007 00:00:00', Zend_Date::ISO_8601, 'de');

// view our date object
print $date->getIso();

// the date stays unchanged even after changeing the timezone
date_default_timezone_set('America/Chicago');
print $date->getIso();

$otherdate = clone $date;
$otherdate->setTimezone('Brazil/Acre');

// view our date object
print $otherdate->getIso();

// set the object to the actual systems timezone
$lastdate = clone $date;
$lastdate->setTimezone();

// view our date object
print $lastdate->getIso();
一般日期函数的常量
Zend_Date
Zend Framework手册 中文版
Zend_Db
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Date
  • 简介
  • 操作理论
  • 基本方法
  • Zend_Date API 概述
  • 生成日期
  • 一般日期函数的常量
  • Working 范例


Zend_Db - Zend Framework Manual

Working 范例
Zend Framework Reference
Zend Framework手册 中文版
Zend_Db_Adapter

Zend_Db

Table of Contents
  • Zend_Db_Adapter
  • Zend_Db_Statement
  • Zend_Db_Profiler
  • Zend_Db_Select
  • Zend_Db_Table
  • Zend_Db_Table_Row
  • Zend_Db_Table_Rowset
  • Zend_Db_Table Relationships
  • Zend_Db_Table_Definition
Working 范例
Zend Framework Reference
Zend Framework手册 中文版
Zend_Db_Adapter
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


Zend_Db_Adapter - Zend Framework Manual

Zend_Db
Zend_Db
Zend Framework手册 中文版
Zend_Db_Statement

Zend_Db_Adapter

简介

Zend_Db_Adapter是zendfrmaeword的数据库抽象层api. 基于pdo, 你可以使用 Zend_Db_Adapter 连接和处理多种 数据库,包括:microsoft SQL Server,MySql,SQLite等等.

要针对不同的数据库实例化一个 Zend_Db_Adapter 对象, 需要 将adapter的名字和描述数据库连接的参数数组作为参数，静态调用 Zend_Db::factory()方法。例如，连接到一个数据库名称为 “camelot”，用户名为“malory”的本地mysql数据库，可以进行如下操作:

<?php

require_once 'Zend/Db.php';

$params = array ('host'     => '127.0.0.1',
                 'username' => 'malory',
                 'password' => '******',
                 'dbname'   => 'camelot');

$db = Zend_Db::factory('PDO_MYSQL', $params);

?>

同样，连接到一个库名为“camelot”的SQLite数据库:

<?php

require_once 'Zend/Db.php';

$params = array ('dbname' => 'camelot');

$db = Zend_Db::factory('PDO_SQLITE', $params);

?>

任一种方法都可以让你使用同样的api查询数据库。

添加引号防止数据库攻击

你应该处理将在sql语句中使用的条件值；这对于防止sql语句攻击是很有好处的。 Zend_Db_Adapter (通过pdo)提供了两种方法帮助你手动的为条件值加上引号。

第一种是quote() 方法. 该方法会根据数据库adapter为标量加上 合适的引号;假如你试图对一个数组做quote操作, 它将为数组中 每个元素加上引号,并用","分隔返回. (对于参数很多的函数来说,这点是很有帮助的).

<?php

// 创建一个$db对象,假设数据库adapter为mysql.

// 为标量加引号
$value = $db->quote('St John"s Wort');
// $value 现在变成了 '"St John\"s Wort"' (注意两边的引号)

// 为数组加引号
$value = $db->quote(array('a', 'b', 'c');
// $value 现在变成了 '"a", "b", "c"' (","分隔的字符串)

?>

第二种是 quoteInto() 方法. 你提供一个包含问号占 位符的基础字符串 , 然后在该位置加入带引号的标量或者数组. 该 方法对于随需构建查询sql语句和条件语句是很有帮助的. 使用 quoteInto处理过的标量和数组返回结果与quote() 方法相同.

<?php

// 创建一个$db对象,假设数据库adapter为mysql.

// 在where语句中为标量加上引号
$where = $db->quoteInto('id = ?', 1);
// $where 现在为 'id = "1"' (注意两边的引号)

// 在where语句中为数组加上引号
$where = $db->quoteInto('id IN(?)', array(1, 2, 3));
// $where 现在为 'id IN("1", "2", "3")' (一个逗号分隔的字符串)

?>

直接查询

一旦你得到了一个Zend_Db_Adapter 实例, 你可以直接 执行sql语句进行查询. Zend_Db_Adapter 传送这些sql语 句到底层的PDO对象，由PDO对象组合并执行他们，在有查询结果的情况 下，返回一个PDOStatement对象以便对结果进行处理。

<?php

// 创建一个$db对象,然后查询数据库
// 使用完整的sql语句直接进行查询.
$sql = $db->quoteInto(
    'SELECT * FROM example WHERE date > ?',
    '2006-01-01'
);
$result = $db->query($sql);

// 使用PDOStatement对象$result将所有结果数据放到一个数组中
$rows = $result->fetchAll();

?>

你可以将数据自动的绑定到你的查询中。这意味着你在查询中可以设定 多个指定的占位符，然后传送一个数组数据以代替这些占位符。这些替 换的数据是自动进行加引号处理的，为防止数据库攻击提供了更强的安 全性。

<?php

// 创建一个$db对象,然后查询数据库.
// 这一次，使用绑定的占位符.
$result = $db->query(
    'SELECT * FROM example WHERE date > :placeholder',
    array('placeholder' => '2006-01-01')
);

// 使用PDOStatement对象$result将所有结果数据放到一个数组中
$rows = $result->fetchAll();

?>

或者,你也可以手工设置sql语句和绑定数据到sql语句。这一功能通过 prepare() 方法得到一个设定好的PDOStatement对象，以便直 接进行数据库操作.

<?php

// 创建一个$db对象,然后查询数据库.
// 这次, 设定一个 PDOStatement 对象进行手工绑定.
$stmt = $db->prepare('SELECT * FROM example WHERE date > :placeholder');
$stmt->bindValue('placeholder', '2006-01-01');
$stmt->execute();

// 使用PDOStatement对象$result将所有结果数据放到一个数组中
$rows = $stmt->fetchAll();

?>

事务处理

默认情况下，PDO(因此 Zend_Db_Adapter 也是)是采用自动commit模式。 也就是说，所有的数据库操作执行时就做了commit操作。假如你试图执行事务处理，最 简单的是调用 beginTransaction() 方法，然后选择commit或者rollback。 之后,Zend_Db_Adapter会回到自动commit模式下，直到你再次调用 beginTransaction()方法

<?php

// 创建一个 $db对象, 然后开始做一个事务处理.
$db->beginTransaction();

// 尝试数据库操作.
// 假如成功,commit该操作;
// 假如, roll back.
try {
    $db->query(...);
    $db->commit();
} catch (Exception $e) {
    $db->rollBack();
    echo $e->getMessage();
}

?>

插入数据行

为了方便起见，你可以使用 insert()方法将要插入的数据绑定并创建 一个insert语句（绑定的数据是自动进行加引号处理以避免数据库攻击的）

返回值并 不是 最后插入的数据的id，这样做的原因在于一些表 并没有一个自增的字段；相反的，这个插入的返回值是改变的数据行数(通常情况为1)。 假如你需要最后插入的数据id，可以在insert执行后调用 lastInsertId() 方法。

<?php

//
// INSERT INTO round_table
//     (noble_title, first_name, favorite_color)
//     VALUES ("King", "Arthur", "blue");
//

// 创建一个 $db对象, 然后...
// 以"列名"=>"数据"的格式格式构造插入数组,插入数据行
$row = array (
    'noble_title'    => 'King',
    'first_name'     => 'Arthur',
    'favorite_color' => 'blue',
);

// 插入数据的数据表
$table = 'round_table';

// i插入数据行并返回行数
$rows_affected = $db->insert($table, $row);
$last_insert_id = $db->lastInsertId();

?>

更新数据行

为了方便起见，你可以使用 update() 方法确定需要update的数据并且创建一个 update语句（确定的数据是自动加引号处理以避免数据库攻击的）。

你可以提供一个可选的where语句说明update的条件（注意：where语句并 不是一个绑定参数，所以你需要自己数据进行加引号的操作）。

<?php

//
// UPDATE round_table
//     SET favorite_color = "yellow"
//     WHERE first_name = "Robin";
//

// 创建一个 $db对象, 然后...
// 以"列名"=>"数据"的格式构造更新数组,更新数据行
$set = array (
    'favorite_color' => 'yellow',
);

// 更新的数据表
$table = 'round_table';

// where语句
$where = $db->quoteInto('first_name = ?', 'Robin');

// 更新表数据,返回更新的行数
$rows_affected = $db->update($table, $set, $where);

?>

删除数据行

为了方便起见，你可以使用 delete() 方法创建一个delete语句；你 也可以提供一个where语句以说明数据的删除条件。（注意：where语句并不是一个绑 定参数，所以你需要自己进行数据加引号处理）。

<?php

//
// 需要删除数据的表
//     WHERE first_name = "Patsy";
//

// 创建一个 $db对象, 然后...
// 设定需要删除数据的表
$table = 'round_table';

// where条件语句
$where = $db->quoteInto('first_name = ?', 'Patsy');

// 删除数据并得到影响的行数
$rows_affected = $db->delete($table, $where);

?>

取回查询结果

尽管你可以使用query()方法直接对数据库进行操作，但是通常情况 下，仍然还是需要选择数据行并返回结果。以fetch开头的一系列的 方法可以实现这个要求。对于每一种 fetch系列 的方法来说，你需 要传送一个select的sql语句；假如你在操作语句中使用指定的占位符，你也可以 传送一个绑定数据的数组对你的操作语句进行处理和替换。 Fetch系列 的方法包括：

  • fetchAll()

  • fetchAssoc()

  • fetchCol()

  • fetchOne()

  • fetchPairs()

  • fetchRow()

<?php

// 创建一个 $db对象, 然后...

// 取回结果集中所有字段的值,作为连续数组返回
$result = $db->fetchAll(
    "SELECT * FROM round_table WHERE noble_title = :title",
    array('title' => 'Sir')
);

// 取回结果集中所有字段的值,作为关联数组返回
// 第一个字段作为码
$result = $db->fetchAssoc(
    "SELECT * FROM round_table WHERE noble_title = :title",
    array('title' => 'Sir')
);

// 取回所有结果行的第一个字段名
$result = $db->fetchCol(
    "SELECT first_name FROM round_table WHERE noble_title = :title",
    array('title' => 'Sir')
);

// 只取回第一个字段值
$result = $db->fetchOne(
    "SELECT COUNT(*) FROM round_table WHERE noble_title = :title",
    array('title' => 'Sir')
);

// 取回一个相关数组,第一个字段值为码
// 第二个字段为值
$result = $db->fetchPairs(
    "SELECT first_name, favorite_color FROM round_table WHERE noble_title = :title",
    array('title' => 'Sir')
);

// 只取回结果集的第一行
$result = $db->fetchRow(
    "SELECT * FROM round_table WHERE first_name = :name",
    array('name' => 'Lancelot')
);

?>
Zend_Db
Zend_Db
Zend Framework手册 中文版
Zend_Db_Statement
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Db
  • Zend_Db_Adapter
  • Zend_Db_Statement
  • Zend_Db_Profiler
  • Zend_Db_Select
  • Zend_Db_Table
  • Zend_Db_Table_Row
  • Zend_Db_Table_Rowset
  • Zend_Db_Table Relationships
  • Zend_Db_Table_Definition


Zend_Db_Statement - Zend Framework Manual

Zend_Db_Adapter
Zend_Db
Zend Framework手册 中文版
Zend_Db_Profiler

Zend_Db_Statement

In addition to convenient methods such as fetchAll() and insert() documented in Zend_Db_Adapter, you can use a statement object to gain more options for running queries and fetching result sets. This section describes how to get an instance of a statement object, and how to use its methods.

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.

Example #1 Creating a SQL statement object with query()

  1. $stmt = $db->query(
  2.             'SELECT * FROM bugs WHERE reported_by = ? AND bug_status = ?',
  3.             array('goofy', 'FIXED')
  4.         );

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.

You can create a statement with its constructor, but this is less typical usage. There is no factory method to create this object, so you need to load the specific statement class and call its constructor. Pass the Adapter object as the first argument, and a string containing an SQL statement as the second argument. The statement is prepared, but not executed.

Example #2 Using a SQL statement constructor

  1. $sql = 'SELECT * FROM bugs WHERE reported_by = ? AND bug_status = ?';
  2.
  3. $stmt = new Zend_Db_Statement_Mysqli($db, $sql);

Executing a Statement

You need to execute a statement object if you create it using its constructor, or if you want to execute the same statement multiple times. Use the execute() method of the statement object. The single argument is an array of value to bind to parameter placeholders in the statement.

If you use positional parameters, or those that are marked with a question mark symbol ('?'), pass the bind values in a plain array.

Example #3 Executing a statement with positional parameters

  1. $sql = 'SELECT * FROM bugs WHERE reported_by = ? AND bug_status = ?';
  2.
  3. $stmt = new Zend_Db_Statement_Mysqli($db, $sql);
  4.
  5. $stmt->execute(array('goofy', 'FIXED'));

If you use 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.

Example #4 Executing a statement with named parameters

  1. $sql = 'SELECT * FROM bugs WHERE ' .
  2.        'reported_by = :reporter AND bug_status = :status';
  3.
  4. $stmt = new Zend_Db_Statement_Mysqli($db, $sql);
  5.
  6. $stmt->execute(array(':reporter' => 'goofy', ':status' => 'FIXED'));

PDO statements support both positional parameters and named parameters, but not both types in a single SQL statement. Some of the Zend_Db_Statement classes for non-PDO extensions may support only one type of parameter or the other.

Fetching Results from a SELECT Statement

You can call methods on the statement object to retrieve rows from SQL statements that produce result set. SELECT, SHOW, DESCRIBE and EXPLAIN are examples of statements that produce a result set. INSERT, UPDATE, and DELETE are examples of statements that don't produce a result set. You can execute the latter SQL statements using Zend_Db_Statement, but you cannot call methods to fetch rows of results from them.

Fetching a Single Row from a Result Set

To retrieve one row from the result set, use the fetch() method of the statement object. All three arguments of this method are optional:

  • Fetch style is the first argument. This controls the structure in which the row is returned. See for a description of the valid values and the corresponding data formats.

  • Cursor orientation is the second argument. The default is Zend_Db::FETCH_ORI_NEXT, which simply means that each call to fetch() returns the next row in the result set, in the order returned by the RDBMS.

  • Offset is the third argument. If the cursor orientation is Zend_Db::FETCH_ORI_ABS, then the offset number is the ordinal number of the row to return. If the cursor orientation is Zend_Db::FETCH_ORI_REL, then the offset number is relative to the cursor position before fetch() was called.

fetch() returns FALSE if all rows of the result set have been fetched.

Example #5 Using fetch() in a loop

  1. $stmt = $db->query('SELECT * FROM bugs');
  2.
  3. while ($row = $stmt->fetch()) {
  4.     echo $row['bug_description'];
  5. }

See also » PDOStatement::fetch().

Fetching a Complete Result Set

To retrieve all the rows of the result set in one step, use the fetchAll() method. This is equivalent to calling the fetch() method in a loop and returning all the rows in an array. The fetchAll() method accepts two arguments. The first is the fetch style, as described above, and the second indicates the number of the column to return, when the fetch style is Zend_Db::FETCH_COLUMN.

Example #6 Using fetchAll()

  1. $stmt = $db->query('SELECT * FROM bugs');
  2.
  3. $rows = $stmt->fetchAll();
  4.
  5. echo $rows[0]['bug_description'];

See also » PDOStatement::fetchAll().

Changing the Fetch Mode

By default, the statement object returns rows of the result set as associative arrays, mapping column names to column values. You can specify a different format for the statement class to return rows, just as you can in the Adapter class. You can use the setFetchMode() method of the statement object to specify the fetch mode. Specify the fetch mode using Zend_Db class constants FETCH_ASSOC, FETCH_NUM, FETCH_BOTH, FETCH_COLUMN, and FETCH_OBJ. See for more information on these modes. Subsequent calls to the statement methods fetch() or fetchAll() use the fetch mode that you specify.

Example #7 Setting the fetch mode

  1. $stmt = $db->query('SELECT * FROM bugs');
  2.
  3. $stmt->setFetchMode(Zend_Db::FETCH_NUM);
  4.
  5. $rows = $stmt->fetchAll();
  6.
  7. echo $rows[0][0];

See also » PDOStatement::setFetchMode().

Fetching a Single Column from a Result Set

To return a single column from the next row of the result set, use fetchColumn(). The optional argument is the integer index of the column, and it defaults to 0. This method returns a scalar value, or FALSE if all rows of the result set have been fetched.

Note this method operates differently than the fetchCol() method of the Adapter class. The fetchColumn() method of a statement returns a single value from one row. The fetchCol() method of an adapter returns an array of values, taken from the first column of all rows of the result set.

Example #8 Using fetchColumn()

  1. $stmt = $db->query('SELECT bug_id, bug_description, bug_status FROM bugs');
  2.
  3. $bug_status = $stmt->fetchColumn(2);

See also » PDOStatement::fetchColumn().

Fetching a Row as an Object

To retrieve a row from the result set structured as an object, use the fetchObject(). This method takes two optional arguments. The first argument is a string that names the class name of the object to return; the default is 'stdClass'. The second argument is an array of values that will be passed to the constructor of that class.

Example #9 Using fetchObject()

  1. $stmt = $db->query('SELECT bug_id, bug_description, bug_status FROM bugs');
  2.
  3. $obj = $stmt->fetchObject();
  4.
  5. echo $obj->bug_description;

See also » PDOStatement::fetchObject().

Zend_Db_Adapter
Zend_Db
Zend Framework手册 中文版
Zend_Db_Profiler
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Db
  • Zend_Db_Adapter
  • Zend_Db_Statement
  • Zend_Db_Profiler
  • Zend_Db_Select
  • Zend_Db_Table
  • Zend_Db_Table_Row
  • Zend_Db_Table_Rowset
  • Zend_Db_Table Relationships
  • Zend_Db_Table_Definition


Zend_Db_Profiler - Zend Framework Manual

Zend_Db_Statement
Zend_Db
Zend Framework手册 中文版
Zend_Db_Select

Zend_Db_Profiler

Introduction

Zend_Db_Profiler can be enabled to allow profiling of queries. Profiles include the queries processed by the adapter as well as elapsed time to run the queries, allowing inspection of the queries that have been performed without needing to add extra debugging code to classes. Advanced usage also allows the developer to filter which queries are profiled.

Enable the profiler by either passing a directive to the adapter constructor, or by asking the adapter to enable it later.

  1. $params = array(
  2.     'host'     => '127.0.0.1',
  3.     'username' => 'webuser',
  4.     'password' => 'xxxxxxxx',
  5.     'dbname'   => 'test'
  6.     'profiler' => true  // turn on profiler
  7.                         // set to false to disable (disabled by default)
  8. );
  9.
  10. $db = Zend_Db::factory('PDO_MYSQL', $params);
  11.
  12. // turn off profiler:
  13. $db->getProfiler()->setEnabled(false);
  14.
  15. // turn on profiler:
  16. $db->getProfiler()->setEnabled(true);

The value of the 'profiler' option is flexible. It is interpreted differently depending on its type. Most often, you should use a simple boolean value, but other types enable you to customize the profiler behavior.

A boolean argument sets the profiler to enabled if it is a TRUE value, or disabled if FALSE. The profiler class is the adapter's default profiler class, Zend_Db_Profiler.

  1. $params['profiler'] = true;
  2. $db = Zend_Db::factory('PDO_MYSQL', $params);

An instance of a profiler object makes the adapter use that object. The object type must be Zend_Db_Profiler or a subclass thereof. Enabling the profiler is done separately.

  1. $profiler = MyProject_Db_Profiler();
  2. $profiler->setEnabled(true);
  3. $params['profiler'] = $profiler;
  4. $db = Zend_Db::factory('PDO_MYSQL', $params);

The argument can be an associative array containing any or all of the keys 'enabled', 'instance', and 'class'. The 'enabled' and 'instance' keys correspond to the boolean and instance types documented above. The 'class' key is used to name a class to use for a custom profiler. The class must be Zend_Db_Profiler or a subclass. The class is instantiated with no constructor arguments. The 'class' option is ignored when the 'instance' option is supplied.

  1. $params['profiler'] = array(
  2.     'enabled' => true,
  3.     'class'   => 'MyProject_Db_Profiler'
  4. );
  5. $db = Zend_Db::factory('PDO_MYSQL', $params);

Finally, the argument can be an object of type Zend_Config containing properties, which are treated as the array keys described above. For example, a file "config.ini" might contain the following data:

  1. [main]
  2. db.profiler.class   = "MyProject_Db_Profiler"
  3. db.profiler.enabled = true

This configuration can be applied by the following PHP code:

  1. $config = new Zend_Config_Ini('config.ini', 'main');
  2. $params['profiler'] = $config->db->profiler;
  3. $db = Zend_Db::factory('PDO_MYSQL', $params);

The 'instance' property may be used as in the following:

  1. $profiler = new MyProject_Db_Profiler();
  2. $profiler->setEnabled(true);
  3. $configData = array(
  4.     'instance' => $profiler
  5.     );
  6. $config = new Zend_Config($configData);
  7. $params['profiler'] = $config;
  8. $db = Zend_Db::factory('PDO_MYSQL', $params);

Using the Profiler

At any point, grab the profiler using the adapter's getProfiler() method:

  1. $profiler = $db->getProfiler();

This returns a Zend_Db_Profiler object instance. With that instance, the developer can examine your queries using a variety of methods:

  • getTotalNumQueries() returns the total number of queries that have been profiled.

  • getTotalElapsedSecs() returns the total number of seconds elapsed for all profiled queries.

  • getQueryProfiles() returns an array of all query profiles.

  • getLastQueryProfile() returns the last (most recent) query profile, regardless of whether or not the query has finished (if it hasn't, the end time will be NULL)

  • clear() clears any past query profiles from the stack.

The return value of getLastQueryProfile() and the individual elements of getQueryProfiles() are Zend_Db_Profiler_Query objects, which provide the ability to inspect the individual queries themselves:

  • getQuery() returns the SQL text of the query. The SQL text of a prepared statement with parameters is the text at the time the query was prepared, so it contains parameter placeholders, not the values used when the statement is executed.

  • getQueryParams() returns an array of parameter values used when executing a prepared query. This includes both bound parameters and arguments to the statement's execute() method. The keys of the array are the positional (1-based) or named (string) parameter indices.

  • getElapsedSecs() returns the number of seconds the query ran.

The information Zend_Db_Profiler provides is useful for profiling bottlenecks in applications, and for debugging queries that have been run. For instance, to see the exact query that was last run:

  1. $query = $profiler->getLastQueryProfile();
  2.
  3. echo $query->getQuery();

Perhaps a page is generating slowly; use the profiler to determine first the total number of seconds of all queries, and then step through the queries to find the one that ran longest:

  1. $totalTime    = $profiler->getTotalElapsedSecs();
  2. $queryCount   = $profiler->getTotalNumQueries();
  3. $longestTime  = 0;
  4. $longestQuery = null;
  5.
  6. foreach ($profiler->getQueryProfiles() as $query) {
  7.     if ($query->getElapsedSecs() > $longestTime) {
  8.         $longestTime  = $query->getElapsedSecs();
  9.         $longestQuery = $query->getQuery();
  10.     }
  11. }
  12.
  13. echo 'Executed ' . $queryCount . ' queries in ' . $totalTime .
  14.      ' seconds' . "\n";
  15. echo 'Average query length: ' . $totalTime / $queryCount .
  16.      ' seconds' . "\n";
  17. echo 'Queries per second: ' . $queryCount / $totalTime . "\n";
  18. echo 'Longest query length: ' . $longestTime . "\n";
  19. echo "Longest query: \n" . $longestQuery . "\n";

Advanced Profiler Usage

In addition to query inspection, the profiler also allows the developer to filter which queries get profiled. The following methods operate on a Zend_Db_Profiler instance:

Filter by query elapsed time

setFilterElapsedSecs() allows the developer to set a minimum query time before a query is profiled. To remove the filter, pass the method a NULL value.

  1. // Only profile queries that take at least 5 seconds:
  2. $profiler->setFilterElapsedSecs(5);
  3.
  4. // Profile all queries regardless of length:
  5. $profiler->setFilterElapsedSecs(null);

Filter by query type

setFilterQueryType() allows the developer to set which types of queries should be profiled; to profile multiple types, logical OR them. Query types are defined as the following Zend_Db_Profiler constants:

  • Zend_Db_Profiler::CONNECT: connection operations, or selecting a database.

  • Zend_Db_Profiler::QUERY: general database queries that do not match other types.

  • Zend_Db_Profiler::INSERT: any query that adds new data to the database, generally SQL INSERT.

  • Zend_Db_Profiler::UPDATE: any query that updates existing data, usually SQL UPDATE.

  • Zend_Db_Profiler::DELETE: any query that deletes existing data, usually SQL DELETE.

  • Zend_Db_Profiler::SELECT: any query that retrieves existing data, usually SQL SELECT.

  • Zend_Db_Profiler::TRANSACTION: any transactional operation, such as start transaction, commit, or rollback.

As with setFilterElapsedSecs(), you can remove any existing filters by passing NULL as the sole argument.

  1. // profile only SELECT queries
  2. $profiler->setFilterQueryType(Zend_Db_Profiler::SELECT);
  3.
  4. // profile SELECT, INSERT, and UPDATE queries
  5. $profiler->setFilterQueryType(Zend_Db_Profiler::SELECT |
  6.                               Zend_Db_Profiler::INSERT |
  7.                               Zend_Db_Profiler::UPDATE);
  8.
  9. // profile DELETE queries
  10. $profiler->setFilterQueryType(Zend_Db_Profiler::DELETE);
  11.
  12. // Remove all filters
  13. $profiler->setFilterQueryType(null);

Retrieve profiles by query type

Using setFilterQueryType() can cut down on the profiles generated. However, sometimes it can be more useful to keep all profiles, but view only those you need at a given moment. Another feature of getQueryProfiles() is that it can do this filtering on-the-fly, by passing a query type (or logical combination of query types) as its first argument; see this section for a list of the query type constants.

  1. // Retrieve only SELECT query profiles
  2. $profiles = $profiler->getQueryProfiles(Zend_Db_Profiler::SELECT);
  3.
  4. // Retrieve only SELECT, INSERT, and UPDATE query profiles
  5. $profiles = $profiler->getQueryProfiles(Zend_Db_Profiler::SELECT |
  6.                                         Zend_Db_Profiler::INSERT |
  7.                                         Zend_Db_Profiler::UPDATE);
  8.
  9. // Retrieve DELETE query profiles
  10. $profiles = $profiler->getQueryProfiles(Zend_Db_Profiler::DELETE);

Specialized Profilers

A Specialized Profiler is an object that inherits from Zend_Db_Profiler. Specialized Profilers treat profiling information in specific ways.

Profiling with Firebug

Zend_Db_Profiler_Firebug sends profiling infomation to the » Firebug » Console.

All data is sent via the Zend_Wildfire_Channel_HttpHeaders component which uses HTTP headers to ensure the page content is not disturbed. Debugging AJAX requests that require clean JSON and XML responses is possible with this approach.

Requirements:

  • Firefox Browser ideally version 3 but version 2 is also supported.

  • Firebug Firefox Extension which you can download from » https://addons.mozilla.org/en-US/firefox/addon/1843.

  • FirePHP Firefox Extension which you can download from » https://addons.mozilla.org/en-US/firefox/addon/6149.

Example #1 DB Profiling with Zend_Controller_Front

  1. // In your bootstrap file
  2.
  3. $profiler = new Zend_Db_Profiler_Firebug('All DB Queries');
  4. $profiler->setEnabled(true);
  5.
  6. // Attach the profiler to your db adapter
  7. $db->setProfiler($profiler)
  8.
  9. // Dispatch your front controller
  10.
  11. // All DB queries in your model, view and controller
  12. // files will now be profiled and sent to Firebug

Example #2 DB Profiling without Zend_Controller_Front

  1. $profiler = new Zend_Db_Profiler_Firebug('All DB Queries');
  2. $profiler->setEnabled(true);
  3.
  4. // Attach the profiler to your db adapter
  5. $db->setProfiler($profiler)
  6.
  7. $request  = new Zend_Controller_Request_Http();
  8. $response = new Zend_Controller_Response_Http();
  9. $channel  = Zend_Wildfire_Channel_HttpHeaders::getInstance();
  10. $channel->setRequest($request);
  11. $channel->setResponse($response);
  12.
  13. // Start output buffering
  14. ob_start();
  15.
  16. // Now you can run your DB queries to be profiled
  17.
  18. // Flush profiling data to browser
  19. $channel->flush();
  20. $response->sendHeaders();
Zend_Db_Statement
Zend_Db
Zend Framework手册 中文版
Zend_Db_Select
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Db
  • Zend_Db_Adapter
  • Zend_Db_Statement
  • Zend_Db_Profiler
  • Zend_Db_Select
  • Zend_Db_Table
  • Zend_Db_Table_Row
  • Zend_Db_Table_Rowset
  • Zend_Db_Table Relationships
  • Zend_Db_Table_Definition


Zend_Db_Select - Zend Framework Manual

Zend_Db_Profiler
Zend_Db
Zend Framework手册 中文版
Zend_Db_Table

Zend_Db_Select

简介

使用Zend_Db_Select方法是一种不受数据库约束构建select的sql语句的工具 （ares注：用户可以使用该方法生成查询的sql语句，而不需要考虑各种数据 库sql语句的差别）。虽然该方法明显还不完善，但是的确为我们提供一种方 法，帮助我们在不同的后台数据库进行相同的查询工作。除此之外，它还可 以避免sql语句攻击。

创建一个zend_db_select实例最简单的方法就是使用zend_db_adapter::select()方法

<?php

require_once 'Zend/Db.php';

$params = array (
    'host'     => '127.0.0.1',
    'username' => 'malory',
    'password' => '******',
    'dbname'   => 'camelot'
);

$db = Zend_Db::factory('PDO_MYSQL', $params);

$select = $db->select();
// $select现在是一个Zend_Db_Select_PdoMysql对象

?>

你可以使用该对象和它的相应方法构建一个select查询语句，然后生成 字符串符用来传送给zend_db_adapter进行查询或者读取结果。

<?php

//
// SELECT *
//     FROM round_table
//     WHERE noble_title = "Sir"
//     ORDER BY first_name
//     LIMIT 10 OFFSET 20
//

// 你可以使用一种重复定义的方式...
$select->from('round_table', '*');
$select->where('noble_title = ?', 'Sir');
$select->order('first_name');
$select->limit(10,20);

// ...或者使用一种连续定义的方式:
$select->from('round_table', '*')
       ->where('noble_title = ?', 'Sir')
       ->order('first_name')
       ->limit(10,20);

// 但是，读取数据的方法相同
$sql = $select->__toString();
$result = $db->fetchAll($sql);

// 对于以上任一种方式，你都可以传送$select对象本身
// 使用Zend_Db_Select对象的 __toString()方法就可以得到查询语句

$result = $db->fetchAll($select);

?>

你也可以在你的查询语句中使用绑定的参数，而不需要自己为参数加引号。

<?php

//
// SELECT *
//     FROM round_table
//     WHERE noble_title = "Sir"
//     ORDER BY first_name
//     LIMIT 10 OFFSET 20
//

$select->from('round_table', '*')
       ->where('noble_title = :title')
       ->order('first_name')
       ->limit(10,20);

// 读取结果使用绑定的参数
$params = array('title' => 'Sir');
$result = $db->fetchAll($select, $params);

?>

同一表中查询多列数据

当需要从某一个指定的表查询某几列时，可以使用from()方法，将需要 查询的表名和列名都在该方法中指定。表名和列名都可以通过别名代替 ，而且也可以根据需要多次使用from()方法。

<?php

// 创建一个$db对象，假定adapter为Mysql
$select = $db->select();

// 从some_table表中读取a,b,c三列
$select->from('some_table', 'a, b, c');
// 同样可以:
$select->from('some_table', array('a', 'b', 'c');

// 从foo AS bar表中读取列bar.col
$select->from('foo AS bar', 'bar.col');

// 从foo, bar两个表中读取foo.col 别名为col1，bar.col别名为col2
$select->from('foo', 'foo.col AS col1');
$select->from('bar', 'bar.col AS col2');

?>

多表联合查询

当需要进行表联合查询时，可以使用join()方法。首先，设定进行表 联合查询的表名，然后是表联合的条件(ares注：该条件是针对多表 内部连接的条件)，最后是查询的列名。同样，你可以根据需要多次 使用join()方法。

<?php

// 创建一个$db对象，假定adapter为Mysql.
$select = $db->select();

//
// SELECT foo.*, bar.*
//     FROM foo
//     JOIN bar ON foo.id = bar.id
//
$select->from('foo', '*');
$select->join('bar', 'foo.id = bar.id', '*');

?>

目前为止，zend framework只支持普通的内部表结合语法，而不支持左结合 ，右结合，等等外部连接方式。未来版本，将会更多的支持更多的连接方式。

WHERE条件

当需要要增加where条件时，可以使用where（）方法。你可以传送一个 普通的查询语句字符串，也可以传送一个使用？作为占位符的字符串,然 后在占位符处加入通过加引号处理后的数据(将使用Zend_Db_Adapter::quoteInto方法进行数据处理)

Multiple calls to where() will AND the conditions together; if you need to OR a condition, use orWhere().

<?php

// 创建一个$db对象，调用SELECT方法.
$select = $db->select();

//
// SELECT *
//     FROM round_table
//     WHERE noble_title = "Sir"
//     AND favorite_color = "yellow"
//
$select->from('round_table', '*');
$select->where('noble_title = "Sir"'); // embedded value
$select->where('favorite_color = ?', 'yellow'); // quoted value

//
// SELECT *
//     FROM foo
//     WHERE bar = "baz"
//     OR id IN("1", "2", "3")
//
$select->from('foo', '*');
$select->where('bar = ?', 'baz');
$select->orWhere('id IN(?)', array(1, 2, 3);

?>

GROUP BY分句

根据需要，可以多次使用group()方法给查询到的数据进行分组

<?php

// 创建一个$db对象，调用SELECT方法.
$select = $db->select();

//
// SELECT COUNT(id)
//     FROM foo
//     GROUP BY bar, baz
//
$select->from('foo', 'COUNT(id)');
$select->group('bar');
$select->group('baz');

// 同样可以这样调用 group() 方法:
$select->group('bar, baz');

// 还可以:
$select->group(array('bar', 'baz'));

?>

HAVING 条件

当需要在查询结果中加入having条件时，可以使用having()方法。 这种方法与where()方法的功能一样。.

当你多次调用having（）方法时，各个having的条件会“并”在一起进行操作； 假如你需要实现“或 ”操作，可以使用orHaving()方法

<?php

// 创建一个$db对象，调用SELECT方法.
$select = $db->select();

//
// SELECT COUNT(id) AS count_id
//     FROM foo
//     GROUP BY bar, baz
//     HAVING count_id > "1"
//
$select->from('foo', 'COUNT(id) AS count_id');
$select->group('bar, baz');
$select->having('count_id > ?', 1);

?>

ORDER BY 分句

根据需要，可以多次使用order()方法给查询到的数据进行排序

<?php

// 创建一个$db对象，调用SELECT方法.
$select = $db->select();

//
// SELECT * FROM round_table
//     ORDER BY noble_title DESC, first_name ASC
//
$select->from('round_table', '*');
$select->order('noble_title DESC');
$select->order('first_name');

// 同样可以这样调用 order() 方法:
$select->order('noble_title DESC, first_name');

// 还可以:
$select->order(array('noble_title DESC', 'first_name'));

?>

通过总数和偏移量进行LIMIT限制

Zend_db_select可以支持数据库层的limit语句限制。对于一些数据库，例如mysql 和postgresql，实现这些是相对容易的，因为这些数据库本身就支持“limit：count” 语法。

对于其他一些数据库来说，例如微软的sqlserver和oracle，要实现limit功能 就不那么简单了，因为他们本身就根本不支持limit语句。MS-SQL有一个top语 句来实现，而oracle要实现limit功能，查询语句的写法就更特殊一些。由于 zend_db_select内在地工作的方式，我们可以重写select语句以在oracle中 实现上述开源数据库系统的limit功能。

要通过设定查询的总数和偏移量对返回的结果进行限制,可以使用limit()方法， 总数值和一个可选的偏移量作为调用该方法的参数。

<?php

// 首先，一个简单的 "LIMIT :count"
$select = $db->select();
$select->from('foo', '*');
$select->order('id');
$select->limit(10);

//
// 在mysql/psotgreSql/SQLite,可以得到这样的语句：
//
// SELECT * FROM foo
//     ORDER BY id ASC
//     LIMIT 10
//
// 但是在Microsoft SQL下,可以得到这样的语句：
//
// SELECT TOP 10 * FROM FOO
//     ORDER BY id ASC
//
//

// 现在, 是更复杂的 "LIMIT :count OFFSET :offset"方法
$select = $db->select();
$select->from('foo', '*');
$select->order('id');
$select->limit(10, 20);

//
// 在mysql/psotgreSql/SQLite,可以得到这样的语句：
//
// SELECT * FROM foo
//     ORDER BY id ASC
//     LIMIT 10 OFFSET 20
//
// 但是在Microsoft SQL下,由于不支持偏移量功能,可以得到这样sql语句:
//
// SELECT * FROM (
//     SELECT TOP 10 * FROM (
//         SELECT TOP 30 * FROM foo ORDER BY id DESC
//     ) ORDER BY id ASC
// )
//
// Zend_Db_Adapter 可以自动的完成sql语句的动态创建.
//

?>

通过页数和总数进行LIMIT限制

Zend_db_select同样也提供了翻页的limit功能。假如你想要从结果中找到 特定“页数”的结果，使用limitPage()方法；将你需要的页数值和每页显示 的数据值数作为参数传过去即可.

<?php

// 构造基础的select方法:
$select = $db->select();
$select->from('foo', '*');
$select->order('id');

// ... 限制到第三页,每页包括10行数据
$select->limitPage(3, 10);

//
// 在MySQL/PostgreSQL/SQLite下, 可以得到:
//
// SELECT * FROM foo
//     ORDER BY id ASC
//     LIMIT 10 OFFSET 20
//

?>
Zend_Db_Profiler
Zend_Db
Zend Framework手册 中文版
Zend_Db_Table
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Db
  • Zend_Db_Adapter
  • Zend_Db_Statement
  • Zend_Db_Profiler
  • Zend_Db_Select
  • Zend_Db_Table
  • Zend_Db_Table_Row
  • Zend_Db_Table_Rowset
  • Zend_Db_Table Relationships
  • Zend_Db_Table_Definition


Zend_Db_Table - Zend Framework Manual

Zend_Db_Select
Zend_Db
Zend Framework手册 中文版
Zend_Db_Table_Row

Zend_Db_Table

简介

Zend_Db_Table 是Zend Framework的表模块.它通过zend_db_adapter连接到 数据库,为数据库模式检查表对象,并对该表进行操作和查询.

开始

首先需要为抽象类zend_db_table(ares注:该类为抽象类,所以不能直接实例 化,只能先继承该类,然后实例化子类)设定一个默认对数据库adapter;除非你 指定其他类型数据库adapter,否则,所有的zend_db_table类实例都会使用 默认adapter.

<?php
// 建立一个 adapter
require_once 'Zend/Db.php';
$params = array (
    'host'     => '127.0.0.1',
    'username' => 'malory',
    'password' => '******',
    'dbname'   => 'camelot'
);

$db = Zend_Db::factory('PDO_MYSQL', $params);

// 为所有的Zend_Db_Table对象设定默认的adapter
require_once 'Zend/Db/Table.php';
Zend_Db_Table::setDefaultAdapter($db);
?>

接下来,我们假定数据库中存在一个名为”round_table”的表.要对该表 使用zend_db_table,只需继承zend_db_table类创建一个名为RoundTable的 新类.然后我就可以通过该类在数据库中的round_table表中检查,操作数据 行并且取得数据结果.

<?php
class RoundTable extends Zend_Db_Table {}
$table = new RoundTable();
?>

表名和主键

默认情况下,zend_db_table类会将其类名当作数据库中表名(大小写不同 的地方需要添加"_").例如,一个名为SomeTableName的zend_db_table类在 数据库中就对应表”some_table_name”.假如不希望将类名与数据库表名以 这种添加下划线的形式进行对应,可以在定义该类时对$_name进行重构.

<?php
class ClassName extends Zend_Db_Table
{
    // 默认表名为 'class_name'
    // 但是我们也可以对应其它表
    protected $_name = 'another_table_name';
}
?>

zend_db_table类默认字段”id”为表的主键(该字段最好为自增的,但并不 是必须的).假如该表的主键并不是名为”$id”,你可以在定义表实体类时 对$_primary进行重构

<?php
class ClassName extends Zend_Db_Table
{
    // 默认主键为’id’
    // 但我们也可以设定其他列名为主键
    protected $_primary = 'another_column_name';
}
?>

你也可以通过表实体类中_setup()方法设定这些变量;但是需要确保在修改 后再执行一次parent::_setup()方法.

<?php
class ClassName extends Zend_Db_Table
{
    protected function _setup()
    {
        $this->_name = 'another_table_name';
        $this->_primary = 'another_column_name';
        parent::_setup();
    }
}
?>

插入数据

要在表中插入一行新数据,只需要将列名:数据的关联数组作为参数,调 用insert()方法即可.(zend framework)会自动对数据进行加引号处理, 并返回插入的最后一行的id值(注意:这里不同于 zend_db_adapter::insert方法,后者返回的是插入的行数).

<?php
//
// INSERT INTO round_table
//     (noble_title, first_name, favorite_color)
//     VALUES ("King", "Arthur", "blue")
//

class RoundTable extends Zend_Db_Table {}

$table = new RoundTable();

$data = array(
    'noble_title' => 'King',
    'first_name'  => 'Arthur',
    'favorite_color' => 'blue',
)

$id = $table->insert($data);
?>

更新数据

要修改表中的任意行数据,我们可以设定一个列名:数据的关联数组作为参数,调 用update()方法,同是通过一个where条件从句来决定需要改变的行.该方法将会 修改表中数据并返回被修改的行数.

(Zend frameword)将会自动对修改对数据进行加引号处理,但是这种检查不包括 条件分句,所以你需要使用该表的zend_db_adapter对象完成该工作.

<?php
//
// UPDATE round_table
//     SET favorite_color = "yellow"
//     WHERE first_name = "Robin"
//

class RoundTable extends Zend_Db_Table {}

$table = new RoundTable();
$db = $table->getAdapter();

$set = array(
    'favorite_color' => 'yellow',
)

$where = $db->quoteInto('first_name = ?', 'Robin');

$rows_affected = $table->update($set, $where);
?>

Deleting Rows

要删除表中的数据,我们可以调用delete()方法,同时通过一个where条件 分句来决定需要删除的行.该方法将会返回被删除的行数.

(zend framework)不会对条件分句进行加引号处理,所以你需要使用该表 的zend_db_adapter对象完成该工作.

<?php
//
// DELETE FROM round_table
//     WHERE first_name = "Patsy"
//

class RoundTable extends Zend_Db_Table {}

$table = new RoundTable();
$db = $table->getAdapter();

$where = $db->quoteInto('first_name = ?', 'Patsy');

$rows_affected = $table->delete($where);
?>

根据主键查找数据

通过调用find()方法,可以使用主键值轻松地在表中检索数据.假如你只想要查询某 一条数据,该方法将回返回一个zend_db_table_row对象,而当你想要查询多条记录时 ,将会返回一个zend_db_table_rowset对象.

<?php
class RoundTable extends Zend_Db_Table {}

$table = new RoundTable();

// SELECT * FROM round_table WHERE id = "1"
$row = $table->find(1);

// SELECT * FROM round_table WHERE id IN("1", "2", 3")
$rowset = $table->find(array(1, 2, 3));
?>

取回一条记录

虽然通过主键找到相应数据行是很便利的事情,但是在更多的时候,我们是 通过其他一些非主键的条件来查找数据行的.zend_db_table提供了一个 fetchRow()方法可以实现这个功能.我们可以通过一个where条件语句(和一 个可选的order语句)调用fetchRow()方法,然后zend_db_tabel将会返回满 足条件的第一行数据的zend_db_table_row对象.

注意,(zend framework) 将不会对where语句进行加引号处理,所以你需要 通过zend_db_adapter进行数据处理.

<?php
//
// SELECT * FROM round_table
//     WHERE noble_title = "Sir"
//     AND first_name = "Robin"
//     ORDER BY favorite_color
//

class RoundTable extends Zend_Db_Table {}

$table = new RoundTable();
$db = $table->getAdapter();

$where = $db->quoteInto('noble_title = ?', 'Sir')
       . $db->quoteInto('AND first_name = ?', 'Robin');

$order = 'favorite_color';

$row = $table->fetchRow($where, $order);
?>

取回多条记录

假如需要一次检索多条记录.可以使用fetchAll()方法.和使用fetchRow()方法类 似,该方法不仅仅可以设定where和order分句,也可以设定limit-count和 limit-offset值来限制返回的结果数.执行该方法后,把选择的结果作为一个 Zend_Db_Table_Rowset对象返回.

注意,(zend framework) 将不会对where语句进行加引号处理,所以你需要 通过zend_db_adapter进行数据处理.

<?php
class RoundTable extends Zend_Db_Table {}

$table = new RoundTable();
$db = $table->getAdapter();

// SELECT * FROM round_table
//     WHERE noble_title = "Sir"
//     ORDER BY first_name
//     LIMIT 10 OFFSET 20

$where = $db->quoteInto('noble_title = ?', 'Sir');
$order = 'first_name';
$count = 10;
$offset = 20;

$rowset = $table->fetchAll($where, $order, $count, $offset);
?>

Adding Domain Logic

作为Zend Framework的表模块,Zend_Db_Table将它自己很好的封装到独特的domain logic下. 例如,你可以重载insert()和update()方法,以实现在数据更改提交前的操作和验证.

<?php
class RoundTable extends Zend_Db_Table
{
    public function insert($data)
    {
        // 添加一个时间戳
        if (empty($data['created_on'])) {
            $data['created_on'] = time();
        }
        return parent::insert($data);
    }

    public function update($data)
    {
        // 添加一个时间戳
        if (empty($data['updated_on'])) {
            $data['updated_on'] = time();
        }
        return parent::update($data);
    }
}
?>

类似的,你也可以设定自己的find()方法,通过主键外的其他字段来查询数据.

<?php
class RoundTable extends Zend_Db_Table
{
    public function findAllWithName($name)
    {
        $db = $this->getAdapter();
        $where = $db->quoteInto("name = ?", $name);
        $order = "first_name";
        return $this->fetchAll($where, $order);
    }
}
?>
Zend_Db_Select
Zend_Db
Zend Framework手册 中文版
Zend_Db_Table_Row
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Db
  • Zend_Db_Adapter
  • Zend_Db_Statement
  • Zend_Db_Profiler
  • Zend_Db_Select
  • Zend_Db_Table
  • Zend_Db_Table_Row
  • Zend_Db_Table_Rowset
  • Zend_Db_Table Relationships
  • Zend_Db_Table_Definition


Zend_Db_Table_Definition - Zend Framework Manual

Zend_Db_Table Relationships
Zend_Db
Zend Framework手册 中文版
Zend_Debug

Zend_Db_Table_Definition

Introduction

Zend_Db_Table_Definition is a class that can be used to describe the relationships and configuration options that should be used when Zend_Db_Table is used via concrete instantiation.

Basic Usage

For all of the same options that are available when configuring an extended Zend_Db_Table_Abstract class, those options are also available when describing a definition file. This definition file should be passed to the class at instantiation time so that it can know the full definition of all tables in said definition.

Below is a definition that will describe the table names and relationships between table objects. Note: if 'name' is left out of the definition, it will be taken as the key of the defined table (an example of this is in the 'genre' section in the example below.)

Example #1 Describing the Definition of a Database Data Model

  1. $definition = new Zend_Db_Table_Definition(array(
  2.     'author' => array(
  3.         'name' => 'author',
  4.         'dependentTables' => array('book')
  5.         ),
  6.     'book' => array(
  7.         'name' => 'book',
  8.         'referenceMap' => array(
  9.             'author' => array(
  10.                 'columns' => 'author_id',
  11.                 'refTableClass' => 'author',
  12.                 'refColumns' => 'id'
  13.                 )
  14.             )
  15.         ),
  16.     'genre' => null,
  17.     'book_to_genre' => array(
  18.         'referenceMap' => array(
  19.             'book' => array(
  20.                 'columns' => 'book_id',
  21.                 'refTableClass' => 'book',
  22.                 'refColumns' => 'id'
  23.                 ),
  24.             'genre' => array(
  25.                 'columns' => 'genre_id',
  26.                 'refTableClass' => 'genre',
  27.                 'refColumns' => 'id'
  28.                 )
  29.             )
  30.         )
  31.     ));

As you can see, the same options you'd generally see inside of an extended Zend_Db_Table_Abstract class are documented in this array as well. When passed into Zend_Db_Table constructor, this definition is persisted to any tables it will need to create in order to return the proper rows.

Below is an example of the primary table instantiation as well as the findDependentRowset() and findManyToManyRowset() calls that will correspond to the data model described above:

Example #2 Interacting with the described definition

  1. $authorTable = new Zend_Db_Table('author', $definition);
  2. $authors = $authorTable->fetchAll();
  3.
  4. foreach ($authors as $author) {
  5.     echo $author->id
  6.        . ': '
  7.        . $author->first_name
  8.        . ' '
  9.        . $author->last_name
  10.        . PHP_EOL;
  11.     $books = $author->findDependentRowset('book');
  12.     foreach ($books as $book) {
  13.         echo '    Book: ' . $book->title . PHP_EOL;
  14.         $genreOutputArray = array();
  15.         $genres = $book->findManyToManyRowset('genre', 'book_to_genre');
  16.         foreach ($genres as $genreRow) {
  17.             $genreOutputArray[] = $genreRow->name;
  18.         }
  19.         echo '        Genre: ' . implode(', ', $genreOutputArray) . PHP_EOL;
  20.     }
  21. }

Advanced Usage

Sometimes you want to use both paradigms for defining and using the table gateway: both by extension and concrete instantiation. To do this simply leave out any table configurations out of the definition. This will allow Zend_Db_Table to look for the actual refered class instead of the definition key.

Building on the example above, we will allow for one of the table configurations to be a Zend_Db_Table_Abstract extended class, while keeping the rest of the tables as part of the definition. We will also show how one would interact with this new definition.

Example #3 Interacting A Mixed Use Zend_Db_Table Definition

  1. class MyBook extends Zend_Db_Table_Abstract
  2. {
  3.     protected $_name = 'book';
  4.     protected $_referenceMap = array(
  5.         'author' => array(
  6.             'columns' => 'author_id',
  7.             'refTableClass' => 'author',
  8.             'refColumns' => 'id'
  9.             )
  10.         );
  11. }
  12.
  13. $definition = new Zend_Db_Table_Definition(array(
  14.     'author' => array(
  15.         'name' => 'author',
  16.         'dependentTables' => array('MyBook')
  17.         ),
  18.     'genre' => null,
  19.     'book_to_genre' => array(
  20.         'referenceMap' => array(
  21.             'book' => array(
  22.                 'columns' => 'book_id',
  23.                 'refTableClass' => 'MyBook',
  24.                 'refColumns' => 'id'
  25.                 ),
  26.             'genre' => array(
  27.                 'columns' => 'genre_id',
  28.                 'refTableClass' => 'genre',
  29.                 'refColumns' => 'id'
  30.                 )
  31.             )
  32.         )
  33.     ));
  34.
  35. $authorTable = new Zend_Db_Table('author', $definition);
  36. $authors = $authorTable->fetchAll();
  37.
  38. foreach ($authors as $author) {
  39.     echo $author->id
  40.        . ': '
  41.        . $author->first_name
  42.        . ' '
  43.        . $author->last_name
  44.        . PHP_EOL;
  45.     $books = $author->findDependentRowset(new MyBook());
  46.     foreach ($books as $book) {
  47.         echo '    Book: ' . $book->title . PHP_EOL;
  48.         $genreOutputArray = array();
  49.         $genres = $book->findManyToManyRowset('genre', 'book_to_genre');
  50.         foreach ($genres as $genreRow) {
  51.             $genreOutputArray[] = $genreRow->name;
  52.         }
  53.         echo '        Genre: ' . implode(', ', $genreOutputArray) . PHP_EOL;
  54.     }
  55. }
Zend_Db_Table Relationships
Zend_Db
Zend Framework手册 中文版
Zend_Debug
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Db
  • Zend_Db_Adapter
  • Zend_Db_Statement
  • Zend_Db_Profiler
  • Zend_Db_Select
  • Zend_Db_Table
  • Zend_Db_Table_Row
  • Zend_Db_Table_Rowset
  • Zend_Db_Table Relationships
  • Zend_Db_Table_Definition


Zend_Db_Table Relationships - Zend Framework Manual

Zend_Db_Table_Rowset
Zend_Db
Zend Framework手册 中文版
Zend_Db_Table_Definition

Zend_Db_Table Relationships

Introduction

Tables have relationships to each other in a relational database. An entity in one table can be linked to one or more entities in another table by using referential integrity constraints defined in the database schema.

The Zend_Db_Table_Row class has methods for querying related rows in other tables.

Defining Relationships

Define classes for each of your tables, extending the abstract class Zend_Db_Table_Abstract, as described in . Also see for a description of the example database for which the following example code is designed.

Below are the PHP class definitions for these tables:

  1. class Accounts extends Zend_Db_Table_Abstract
  2. {
  3.     protected $_name            = 'accounts';
  4.     protected $_dependentTables = array('Bugs');
  5. }
  6.
  7. class Products extends Zend_Db_Table_Abstract
  8. {
  9.     protected $_name            = 'products';
  10.     protected $_dependentTables = array('BugsProducts');
  11. }
  12.
  13. class Bugs extends Zend_Db_Table_Abstract
  14. {
  15.     protected $_name            = 'bugs';
  16.
  17.     protected $_dependentTables = array('BugsProducts');
  18.
  19.     protected $_referenceMap    = array(
  20.         'Reporter' => array(
  21.             'columns'           => 'reported_by',
  22.             'refTableClass'     => 'Accounts',
  23.             'refColumns'        => 'account_name'
  24.         ),
  25.         'Engineer' => array(
  26.             'columns'           => 'assigned_to',
  27.             'refTableClass'     => 'Accounts',
  28.             'refColumns'        => 'account_name'
  29.         ),
  30.         'Verifier' => array(
  31.             'columns'           => array('verified_by'),
  32.             'refTableClass'     => 'Accounts',
  33.             'refColumns'        => array('account_name')
  34.         )
  35.     );
  36. }
  37.
  38. class BugsProducts extends Zend_Db_Table_Abstract
  39. {
  40.     protected $_name = 'bugs_products';
  41.
  42.     protected $_referenceMap    = array(
  43.         'Bug' => array(
  44.             'columns'           => array('bug_id'),
  45.             'refTableClass'     => 'Bugs',
  46.             'refColumns'        => array('bug_id')
  47.         ),
  48.         'Product' => array(
  49.             'columns'           => array('product_id'),
  50.             'refTableClass'     => 'Products',
  51.             'refColumns'        => array('product_id')
  52.         )
  53.     );
  54.
  55. }

If you use Zend_Db_Table to emulate cascading UPDATE and DELETE operations, declare the $_dependentTables array in the class for the parent table. List the class name for each dependent table. Use the class name, not the physical name of the SQL table.

Note: Skip declaration of $_dependentTables if you use referential integrity constraints in the RDBMS server to implement cascading operations. See Cascading Write Operations for more information.

Declare the $_referenceMap array in the class for each dependent table. This is an associative array of reference "rules". A reference rule identifies which table is the parent table in the relationship, and also lists which columns in the dependent table reference which columns in the parent table.

The rule key is a string used as an index to the $_referenceMap array. This rule key is used to identify each reference relationship. Choose a descriptive name for this rule key. It's best to use a string that can be part of a PHP method name, as you will see later.

In the example PHP code above, the rule keys in the Bugs table class are: 'Reporter', 'Engineer', 'Verifier', and 'Product'.

The value of each rule entry in the $_referenceMap array is also an associative array. The elements of this rule entry are described below:

  • columns => A string or an array of strings naming the foreign key column name(s) in the dependent table.

    It's common for this to be a single column, but some tables have multi-column keys.

  • refTableClass => The class name of the parent table. Use the class name, not the physical name of the SQL table.

    It's common for a dependent table to have only one reference to its parent table, but some tables have multiple references to the same parent table. In the example database, there is one reference from the bugs table to the products table, but three references from the bugs table to the accounts table. Put each reference in a separate entry in the $_referenceMap array.

  • refColumns => A string or an array of strings naming the primary key column name(s) in the parent table.

    It's common for this to be a single column, but some tables have multi-column keys. If the reference uses a multi-column key, the order of columns in the 'columns' entry must match the order of columns in the 'refColumns' entry.

    It is optional to specify this element. If you don't specify the refColumns, the column(s) reported as the primary key columns of the parent table are used by default.

  • onDelete => The rule for an action to execute if a row is deleted in the parent table. See Cascading Write Operations for more information.

  • onUpdate => The rule for an action to execute if values in primary key columns are updated in the parent table. See Cascading Write Operations for more information.

Fetching a Dependent Rowset

If you have a Row object as the result of a query on a parent table, you can fetch rows from dependent tables that reference the current row. Use the method:

  1. $row->findDependentRowset($table, [$rule]);

This method returns a Zend_Db_Table_Rowset_Abstract object, containing a set of rows from the dependent table $table that refer to the row identified by the $row object.

The first argument $table can be a string that specifies the dependent table by its class name. You can also specify the dependent table by using an object of that table class.

Example #1 Fetching a Dependent Rowset

This example shows getting a Row object from the table Accounts, and finding the Bugs reported by that account.

  1. $accountsTable = new Accounts();
  2. $accountsRowset = $accountsTable->find(1234);
  3. $user1234 = $accountsRowset->current();
  4.
  5. $bugsReportedByUser = $user1234->findDependentRowset('Bugs');

The second argument $rule is optional. It is a string that names the rule key in the $_referenceMap array of the dependent table class. If you don't specify a rule, the first rule in the array that references the parent table is used. If you need to use a rule other than the first, you need to specify the key.

In the example code above, the rule key is not specified, so the rule used by default is the first one that matches the parent table. This is the rule 'Reporter'.

Example #2 Fetching a Dependent Rowset By a Specific Rule

This example shows getting a Row object from the table Accounts, and finding the Bugs assigned to be fixed by the user of that account. The rule key string that corresponds to this reference relationship in this example is 'Engineer'.

  1. $accountsTable = new Accounts();
  2. $accountsRowset = $accountsTable->find(1234);
  3. $user1234 = $accountsRowset->current();
  4.
  5. $bugsAssignedToUser = $user1234->findDependentRowset('Bugs', 'Engineer');

You can also add criteria, ordering and limits to your relationships using the parent row's select object.

Example #3 Fetching a Dependent Rowset using a Zend_Db_Table_Select

This example shows getting a Row object from the table Accounts, and finding the Bugs assigned to be fixed by the user of that account, limited only to 3 rows and ordered by name.

  1. $accountsTable = new Accounts();
  2. $accountsRowset = $accountsTable->find(1234);
  3. $user1234 = $accountsRowset->current();
  4. $select = $accountsTable->select()->order('name ASC')
  5.                                   ->limit(3);
  6.
  7. $bugsAssignedToUser = $user1234->findDependentRowset('Bugs',
  8.                                                      'Engineer',
  9.                                                      $select);
Alternatively, you can query rows from a dependent table using a special mechanism called a "magic method". Zend_Db_Table_Row_Abstract invokes the method: findDependentRowset('<TableClass>', '<Rule>') if you invoke a method on the Row object matching either of the following patterns:

  • $row->find<TableClass>()

  • $row->find<TableClass>By<Rule>()

In the patterns above, <TableClass> and <Rule> are strings that correspond to the class name of the dependent table, and the dependent table's rule key that references the parent table.

Note: Some application frameworks, such as Ruby on Rails, use a mechanism called "inflection" to allow the spelling of identifiers to change depending on usage. For simplicity, Zend_Db_Table_Row does not provide any inflection mechanism. The table identity and the rule key named in the method call must match the spelling of the class and rule key exactly.

Example #4 Fetching Dependent Rowsets using the Magic Method

This example shows finding dependent Rowsets equivalent to those in the previous examples. In this case, the application uses the magic method invocation instead of specifying the table and rule as strings.

  1. $accountsTable = new Accounts();
  2. $accountsRowset = $accountsTable->find(1234);
  3. $user1234 = $accountsRowset->current();
  4.
  5. // Use the default reference rule
  6. $bugsReportedBy = $user1234->findBugs();
  7.
  8. // Specify the reference rule
  9. $bugsAssignedTo = $user1234->findBugsByEngineer();

Fetching a Parent Row

If you have a Row object as the result of a query on a dependent table, you can fetch the row in the parent to which the dependent row refers. Use the method:

  1. $row->findParentRow($table, [$rule]);

There always should be exactly one row in the parent table referenced by a dependent row, therefore this method returns a Row object, not a Rowset object.

The first argument $table can be a string that specifies the parent table by its class name. You can also specify the parent table by using an object of that table class.

Example #5 Fetching the Parent Row

This example shows getting a Row object from the table Bugs (for example one of those bugs with status 'NEW'), and finding the row in the Accounts table for the user who reported the bug.

  1. $bugsTable = new Bugs();
  2. $bugsRowset = $bugsTable->fetchAll(array('bug_status = ?' => 'NEW'));
  3. $bug1 = $bugsRowset->current();
  4.
  5. $reporter = $bug1->findParentRow('Accounts');

The second argument $rule is optional. It is a string that names the rule key in the $_referenceMap array of the dependent table class. If you don't specify a rule, the first rule in the array that references the parent table is used. If you need to use a rule other than the first, you need to specify the key.

In the example above, the rule key is not specified, so the rule used by default is the first one that matches the parent table. This is the rule 'Reporter'.

Example #6 Fetching a Parent Row By a Specific Rule

This example shows getting a Row object from the table Bugs, and finding the account for the engineer assigned to fix that bug. The rule key string that corresponds to this reference relationship in this example is 'Engineer'.

  1. $bugsTable = new Bugs();
  2. $bugsRowset = $bugsTable->fetchAll(array('bug_status = ?', 'NEW'));
  3. $bug1 = $bugsRowset->current();
  4.
  5. $engineer = $bug1->findParentRow('Accounts', 'Engineer');

Alternatively, you can query rows from a parent table using a "magic method". Zend_Db_Table_Row_Abstract invokes the method: findParentRow('<TableClass>', '<Rule>') if you invoke a method on the Row object matching either of the following patterns:

  • $row->findParent<TableClass>([Zend_Db_Table_Select $select])

  • $row->findParent<TableClass>By<Rule>([Zend_Db_Table_Select $select])

In the patterns above, <TableClass> and <Rule> are strings that correspond to the class name of the parent table, and the dependent table's rule key that references the parent table.

Note: The table identity and the rule key named in the method call must match the spelling of the class and rule key exactly.

Example #7 Fetching the Parent Row using the Magic Method

This example shows finding parent Rows equivalent to those in the previous examples. In this case, the application uses the magic method invocation instead of specifying the table and rule as strings.

  1. $bugsTable = new Bugs();
  2. $bugsRowset = $bugsTable->fetchAll(array('bug_status = ?', 'NEW'));
  3. $bug1 = $bugsRowset->current();
  4.
  5. // Use the default reference rule
  6. $reporter = $bug1->findParentAccounts();
  7.
  8. // Specify the reference rule
  9. $engineer = $bug1->findParentAccountsByEngineer();

Fetching a Rowset via a Many-to-many Relationship

If you have a Row object as the result of a query on one table in a many-to-many relationship (for purposes of the example, call this the "origin" table), you can fetch corresponding rows in the other table (call this the "destination" table) via an intersection table. Use the method:

  1. $row->findManyToManyRowset($table,
  2.                            $intersectionTable,
  3.                            [$rule1,
  4.                                [$rule2,
  5.                                    [Zend_Db_Table_Select $select]
  6.                                ]
  7.                            ]);

This method returns a Zend_Db_Table_Rowset_Abstract containing rows from the table $table, satisfying the many-to-many relationship. The current Row object $row from the origin table is used to find rows in the intersection table, and that is joined to the destination table.

The first argument $table can be a string that specifies the destination table in the many-to-many relationship by its class name. You can also specify the destination table by using an object of that table class.

The second argument $intersectionTable can be a string that specifies the intersection table between the two tables in the many-to-many relationship by its class name. You can also specify the intersection table by using an object of that table class.

Example #8 Fetching a Rowset with the Many-to-many Method

This example shows getting a Row object from the origin table Bugs, and finding rows from the destination table Products, representing products related to that bug.

  1. $bugsTable = new Bugs();
  2. $bugsRowset = $bugsTable->find(1234);
  3. $bug1234 = $bugsRowset->current();
  4.
  5. $productsRowset = $bug1234->findManyToManyRowset('Products',
  6.                                                  'BugsProducts');

The third and fourth arguments $rule1 and $rule2 are optional. These are strings that name the rule keys in the $_referenceMap array of the intersection table.

The $rule1 key names the rule for the relationship from the intersection table to the origin table. In this example, this is the relationship from BugsProducts to Bugs.

The $rule2 key names the rule for the relationship from the intersection table to the destination table. In this example, this is the relationship from Bugs to Products.

Similarly to the methods for finding parent and dependent rows, if you don't specify a rule, the method uses the first rule in the $_referenceMap array that matches the tables in the relationship. If you need to use a rule other than the first, you need to specify the key.

In the example code above, the rule key is not specified, so the rules used by default are the first ones that match. In this case, $rule1 is 'Reporter' and $rule2 is 'Product'.

Example #9 Fetching a Rowset with the Many-to-many Method By a Specific Rule

This example shows geting a Row object from the origin table Bugs, and finding rows from the destination table Products, representing products related to that bug.

  1. $bugsTable = new Bugs();
  2. $bugsRowset = $bugsTable->find(1234);
  3. $bug1234 = $bugsRowset->current();
  4.
  5. $productsRowset = $bug1234->findManyToManyRowset('Products',
  6.                                                  'BugsProducts',
  7.                                                  'Bug');

Alternatively, you can query rows from the destination table in a many-to-many relationship using a "magic method." Zend_Db_Table_Row_Abstract invokes the method: findManyToManyRowset('<TableClass>', '<IntersectionTableClass>', '<Rule1>', '<Rule2>') if you invoke a method matching any of the following patterns:

  • $row->find<TableClass>Via<IntersectionTableClass> ([Zend_Db_Table_Select $select])

  • $row->find<TableClass>Via<IntersectionTableClass>By<Rule1> ([Zend_Db_Table_Select $select])

  • $row->find<TableClass>Via<IntersectionTableClass>By<Rule1>And<Rule2> ([Zend_Db_Table_Select $select])

In the patterns above, <TableClass> and <IntersectionTableClass> are strings that correspond to the class names of the destination table and the intersection table, respectively. <Rule1> and <Rule2> are strings that correspond to the rule keys in the intersection table that reference the origin table and the destination table, respectively.

Note: The table identities and the rule keys named in the method call must match the spelling of the class and rule key exactly.

Example #10 Fetching Rowsets using the Magic Many-to-many Method

This example shows finding rows in the destination table of a many-to-many relationship representing products related to a given bug.

  1. $bugsTable = new Bugs();
  2. $bugsRowset = $bugsTable->find(1234);
  3. $bug1234 = $bugsRowset->current();
  4.
  5. // Use the default reference rule
  6. $products = $bug1234->findProductsViaBugsProducts();
  7.
  8. // Specify the reference rule
  9. $products = $bug1234->findProductsViaBugsProductsByBug();

Cascading Write Operations

Note: Declare DRI in the database:
 Declaring cascading operations in Zend_Db_Table is intended only for RDBMS brands that do not support declarative referential integrity (DRI).
For example, if you use MySQL's MyISAM storage engine, or SQLite, these solutions do not support DRI. You may find it helpful to declare the cascading operations with Zend_Db_Table.
If your RDBMS implements DRI and the ON DELETE and ON UPDATE clauses, you should declare these clauses in your database schema, instead of using the cascading feature in Zend_Db_Table. Declaring cascading DRI rules in the RDBMS is better for database performance, consistency, and integrity.
Most importantly, do not declare cascading operations both in the RDBMS and in your Zend_Db_Table class.

You can declare cascading operations to execute against a dependent table when you apply an UPDATE or a DELETE to a row in a parent table.

Example #11 Example of a Cascading Delete

This example shows deleting a row in the Products table, which is configured to automatically delete dependent rows in the Bugs table.

  1. $productsTable = new Products();
  2. $productsRowset = $productsTable->find(1234);
  3. $product1234 = $productsRowset->current();
  4.
  5. $product1234->delete();
  6. // Automatically cascades to Bugs table
  7. // and deletes dependent rows.

Similarly, if you use UPDATE to change the value of a primary key in a parent table, you may want the value in foreign keys of dependent tables to be updated automatically to match the new value, so that such references are kept up to date.

It's usually not necessary to update the value of a primary key that was generated by a sequence or other mechanism. But if you use a natural key that may change value occasionally, it is more likely that you need to apply cascading updates to dependent tables.

To declare a cascading relationship in the Zend_Db_Table, edit the rules in the $_referenceMap. Set the associative array keys 'onDelete' and 'onUpdate' to the string 'cascade' (or the constant self::CASCADE). Before a row is deleted from the parent table, or its primary key values updated, any rows in the dependent table that refer to the parent's row are deleted or updated first.

Example #12 Example Declaration of Cascading Operations

In the example below, rows in the Bugs table are automatically deleted if the row in the Products table to which they refer is deleted. The 'onDelete' element of the reference map entry is set to self::CASCADE.

No cascading update is done in the example below if the primary key value in the parent class is changed. The 'onUpdate' element of the reference map entry is self::RESTRICT. You can get the same result by omitting the 'onUpdate' entry.

  1. class BugsProducts extends Zend_Db_Table_Abstract
  2. {
  3.     ...
  4.     protected $_referenceMap = array(
  5.         'Product' => array(
  6.             'columns'           => array('product_id'),
  7.             'refTableClass'     => 'Products',
  8.             'refColumns'        => array('product_id'),
  9.             'onDelete'          => self::CASCADE,
  10.             'onUpdate'          => self::RESTRICT
  11.         ),
  12.         ...
  13.     );
  14. }

Notes Regarding Cascading Operations

Cascading operations invoked by Zend_Db_Table are not atomic.

This means that if your database implements and enforces referential integrity constraints, a cascading UPDATE executed by a Zend_Db_Table class conflicts with the constraint, and results in a referential integrity violation. You can use cascading UPDATE in Zend_Db_Table only if your database does not enforce that referential integrity constraint.

Cascading DELETE suffers less from the problem of referential integrity violations. You can delete dependent rows as a non-atomic action before deleting the parent row that they reference.

However, for both UPDATE and DELETE, changing the database in a non-atomic way also creates the risk that another database user can see the data in an inconsistent state. For example, if you delete a row and all its dependent rows, there is a small chance that another database client program can query the database after you have deleted the dependent rows, but before you delete the parent row. That client program may see the parent row with no dependent rows, and assume this is the intended state of the data. There is no way for that client to know that its query read the database in the middle of a change.

The issue of non-atomic change can be mitigated by using transactions to isolate your change. But some RDBMS brands don't support transactions, or allow clients to read "dirty" changes that have not been committed yet.

Cascading operations in Zend_Db_Table are invoked only by Zend_Db_Table.

Cascading deletes and updates defined in your Zend_Db_Table classes are applied if you execute the save() or delete() methods on the Row class. However, if you update or delete data using another interface, such as a query tool or another application, the cascading operations are not applied. Even when using update() and delete() methods in the Zend_Db_Adapter class, cascading operations defined in your Zend_Db_Table classes are not executed.

No Cascading INSERT.

There is no support for a cascading INSERT. You must insert a row to a parent table in one operation, and insert row(s) to a dependent table in a separate operation.

Zend_Db_Table_Rowset
Zend_Db
Zend Framework手册 中文版
Zend_Db_Table_Definition
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Db
  • Zend_Db_Adapter
  • Zend_Db_Statement
  • Zend_Db_Profiler
  • Zend_Db_Select
  • Zend_Db_Table
  • Zend_Db_Table_Row
  • Zend_Db_Table_Rowset
  • Zend_Db_Table Relationships
  • Zend_Db_Table_Definition


Zend_Db_Table_Row - Zend Framework Manual

Zend_Db_Table
Zend_Db
Zend Framework手册 中文版
Zend_Db_Table_Rowset

Zend_Db_Table_Row

简介

Zend_Db_Table_Row是Zend Framework的行数据网关.通常来说,你不可以自己实例化Zend_Db_Table_Row, 而是通过调用Zend_Db_Table::find()方法或者Zend_Db_Table::fetchRow()方法将Zend_Db_Table_Row作为 结果数据返回过来.一旦你得到来一个Zend_Db_Table_Row对象,你可以修改记录值(体现为类的属性)然后 调用save()方法可以将更改保存到原表上.

取回一条记录

首先,需要实例化一个Zend_Db_Table类.

<?php
// 设置一个 adapter
require_once 'Zend/Db.php';
$params = array (
    'host'     => '127.0.0.1',
    'username' => 'malory',
    'password' => '******',
    'dbname'   => 'camelot'
);

$db = Zend_Db::factory('PDO_MYSQL', $params);

// 为所有的Zend_Db_Table对象设置默认adapter
require_once 'Zend/Db/Table.php';
Zend_Db_Table::setDefaultAdapter($db);

// 连接到数据库中的某一个表
class RoundTable extends Zend_Db_Table {}
$table = new RoundTable();
?>

接下来,使用Zend_Db_Table::find()方法和主键进行查询,或者使 用Zend_Db_Table::fetchRow()方法查询.得到的返回结果是一个Zend_Db_Table_Row 对象,该对象的属性名采用camelCaps的形式对应数据库中带下划线的表名.例如,表名 若为first_name,那么类中的改属性则为firstName.

<?php
// 从表中取回的结果数据是一个Zend_Db_Table_Row对象
$row = $table->fetchRow('first_name = "Robin"');

//
// $row现在是一个带有多种公有属性的Zend_Db_Table_Row对象
// that map to table columns:
//
// $row->id = '3'
// $row->nobleTitle = 'Sir'
// $row->firstName = 'Robin'
// $row->favoriteColor = 'yellow'
//

?>

修改数据

修改行数据是一件很轻松的事情:只需要按照常规的方法修改类属性.然后调用save()方法 就将改变的结果保存到了数据表中.

<?php
// 连接到数据库中的表
class RoundTable extends Zend_Db_Table {}
$table = new RoundTable();

// 从表中取回的结果数据是一个Zend_Db_Table_Row对象
$row = $table->fetchRow('first_name = "Robin"');

//
// $row现在是一个带有多种公有属性的Zend_Db_Table_Row对象
// that map to table columns:
//
// $row->id = '3'
// $row->nobleTitle = 'Sir'
// $row->firstName = 'Robin'
// $row->favoriteColor = 'yellow'
//
// 改变favorite color字段,并且将变动存储到数据表中.
$row->favoriteColor = 'blue';'
$row->save();
?>

但是,你不能够修改主键的值.假如你试图进行改操作, Zend_Db_Table_Row将抛出一个异常.

<?php
// 连接到数据库中的表
class RoundTable extends Zend_Db_Table {}
$table = new RoundTable();

// fetch a record from the table as a Zend_Db_Table_Row object
$row = $table->fetchRow('first_name = "Robin"');

// 我们尝试修改主键值
try {
    $row->id = 5;
    echo "We should not see this message, as an exception was thrown.";
} catch (Zend_Db_Table_RowException $e) {
    echo $e->getMessage();
}
?>
Zend_Db_Table
Zend_Db
Zend Framework手册 中文版
Zend_Db_Table_Rowset
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Db
  • Zend_Db_Adapter
  • Zend_Db_Statement
  • Zend_Db_Profiler
  • Zend_Db_Select
  • Zend_Db_Table
  • Zend_Db_Table_Row
  • Zend_Db_Table_Rowset
  • Zend_Db_Table Relationships
  • Zend_Db_Table_Definition


Zend_Db_Table_Rowset - Zend Framework Manual

Zend_Db_Table_Row
Zend_Db
Zend Framework手册 中文版
Zend_Db_Table Relationships

Zend_Db_Table_Rowset

简介

Zend_Db_Table_Rowset是 Zend_Db_Table_Row对象集合的迭代器.通常来说,你不可以自己实例化Zend_Db_Table_Rowset, 而是通过调用Zend_Db_Table::find()方法或者fetchAll()方法将Zend_Db_Table_Rowset作为 结果数据返回过来.接下来就可以遍历Zend_Db_Table_Row对象集合并进行修改.

取回结果集

首先,需要实例化一个Zend_Db_Table类.

<?php
// 设置一个 adapter
require_once 'Zend/Db.php';
$params = array (
    'host'     => '127.0.0.1',
    'username' => 'malory',
    'password' => '******',
    'dbname'   => 'camelot'
);

$db = Zend_Db::factory('PDO_MYSQL', $params);

// 为所有的Zend_Db_Table对象设置默认
require_once 'Zend/Db/Table.php';
Zend_Db_Table::setDefaultAdapter($db);

// 连接数据库表
class RoundTable extends Zend_Db_Table {}
$table = new RoundTable();
?>

接下来,可以使用Zend_Db_Table::find()方法和多个键值,或者使用Zend_Db_Table::fetchAll()方法对数据库进行查询, 返回的结果是一个Zend_Db_Table_Rowset对象,可以通过该对象遍历结果集中的每一个Zend_Db_Table_Row对象.

<?php
// 从表中取回多条记录
$rowset = $table->fetchAll();

//
// $rowset现在是一个Zend_Db_Table_Rowset对象,该对象中每条记录就是一个Zend_Db_Table_Row对象
//
?>

遍历结果集

Zend_Db_Table_Rowset实现了简单程序设计语言的迭代器接口,也就是说,可以对Zend_Db_Table_Rowset 对象进行循环处理,就像使用foreach()函数处理数组一样.使用这种方法取回的每一个值都是一个对应表 中数据的Zend_Db_Table_Row对象,你可以查看,修改和保存该对象的属性(即表中的字段值.)

<?php
// 连接到数据库中的表
class RoundTable extends Zend_Db_Table {}
$table = new RoundTable();

// 从表中取回多条记录
$rowset = $table->fetchAll();

// 显示所有的记录
foreach ($rowset as $row) {
    // $row 是一个 Zend_Db_Table_Row 对象
    echo "<p>" . htmlspecialchars($row->nobleTitle) . " "
       . htmlspecialchars($row->firstName) . "'s "
       . "favorite color is " . htmlspecialchars($row->favoriteColor)
       . ".</p>\n";

    // 更新我们显示改行的次数
    // (对应表中的"times_displayed"字段)
    $row->timesDisplayed ++;

    // 保存新记录.
    $row->save();
}
?>
Zend_Db_Table_Row
Zend_Db
Zend Framework手册 中文版
Zend_Db_Table Relationships
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Db
  • Zend_Db_Adapter
  • Zend_Db_Statement
  • Zend_Db_Profiler
  • Zend_Db_Select
  • Zend_Db_Table
  • Zend_Db_Table_Row
  • Zend_Db_Table_Rowset
  • Zend_Db_Table Relationships
  • Zend_Db_Table_Definition


Zend_Debug - Zend Framework Manual

Zend_Db_Table_Definition
Zend Framework Reference
Zend Framework手册 中文版
输出变量的值 (Dumping Variables)

Zend_Debug

Table of Contents
  • 输出变量的值 (Dumping Variables)
Zend_Db_Table_Definition
Zend Framework Reference
Zend Framework手册 中文版
输出变量的值 (Dumping Variables)
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


输出变量的值 (Dumping Variables) - Zend Framework Manual

Zend_Debug
Zend_Debug
Zend Framework手册 中文版
Zend_Dojo

输出变量的值 (Dumping Variables)

静态方法 Zend_Debug::dump() 打印或返回某个表达式或变量的信息。这个简单的调试技术很常用，因为在特别时髦和要求没有初始化、特殊工具或调试环境时很容易使用。

Example #1 dump()方法使用示例

Zend_Debug::dump($var, $label=null, $echo=true);

$var 参数指定了 Zend_Debug::dump() 输出信息的表达式或变量。

$label 标签参数是用来加在 Zend_Debug::dump() 输出信息之前的一段文本。这非常有用，例如你一次要查看多个变量的信息。（你可以为不同变量设置不同label，如“user”，“password”等等，这样不会弄乱--Haohappy注)

Zend_Debug::dump() 是否输出，这取决于$echo参数，如果为true，则会输出结果。无论是否指定$echo参数的值，该方法的返回值都包含表达式或变量的信息。

深入地理解它很有帮助，Zend_Debug::dump() 方法封装 PHP 函数» var_dump()。如果输出流被检测为 web 表达，var_dump() 的输出结果使用 » htmlspecialchars()转义，并封装(X)HTML <pre>标签。

Tip

使用 Zend_Log 进行调试

使用 Zend_Debug::dump() 很方便在开发项目时Debug，你可以很容易地增加或移除它。

你也可以考虑使用 Zend_Log 来调试，用于更长期的非短暂性的调试和监控。例如，你可以使用 DEBUG 记录级别和 Stream 记录器来输出 Zend_Debug::dump() 返回的信息。

Zend_Debug
Zend_Debug
Zend Framework手册 中文版
Zend_Dojo
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Debug
  • 输出变量的值 (Dumping Variables)


Zend_Dojo - Zend Framework Manual

输出变量的值 (Dumping Variables)
Zend Framework Reference
Zend Framework手册 中文版
简介

Zend_Dojo

Table of Contents
  • 简介
  • Zend_Dojo_Data: dojo.data Envelopes
  • Dojo 视图助手
  • Dojo 表单元素和装饰器
  • Zend_Dojo build layer support
输出变量的值 (Dumping Variables)
Zend Framework Reference
Zend Framework手册 中文版
简介
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


简介 - Zend Framework Manual

Zend_Dojo
Zend_Dojo
Zend Framework手册 中文版
Zend_Dojo_Data: dojo.data Envelopes

简介

从1.6.0版开始，Zend Framework包含» Dojo Toolkit 来支持 out-of-the-box 的富 internet 程序开发。和 Dojo 集成的包括：

  • JSON-RPC 支持

  • dojo.data 兼容性

  • 协助设置 Dojo 环境的视图助手

  • Dijit-specific Zend_View 助手

  • Dijit-specific Zend_Form 元素和装饰

Dojo 可以从 Zend Framework 发行版的 externals/dojo/ 目录找到。 这是源代码发行，包括 Dojo 的全部 javascript 源代码，单元测试和构造工具。 你可以把它链接到你的 javascript 目录，复制或使用构造工具来生成你自己的定制， 然后包含到你的项目里。另外，你可以使用提供Dojo的Content Delivery Networks 中的一个 （ZF 支持官方的 AOL CDN 和 Google CDN）。

Zend_Dojo
Zend_Dojo
Zend Framework手册 中文版
Zend_Dojo_Data: dojo.data Envelopes
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Dojo
  • 简介
  • Zend_Dojo_Data: dojo.data Envelopes
  • Dojo 视图助手
  • Dojo 表单元素和装饰器
  • Zend_Dojo build layer support


Zend_Dojo_Data: dojo.data Envelopes - Zend Framework Manual

简介
Zend_Dojo
Zend Framework手册 中文版
Dojo 视图助手

Zend_Dojo_Data: dojo.data Envelopes

Dojo 通过它的 dojo.data 组件为 data-enabled 小部件提供数据抽象。 该组件提供附加数据存储的能力，提供一些关于身份字段和可选的标签字段的元数据以及 从数据存储查询、排序和获取记录和一组记录的 API。

dojo.data 常和XmlHttpRequest一起使用来从服务器取出动态数据。 它的基本机制是扩展 QueryReadStore 来指向一个 URL 并指定查询信息，服务器端就用 下列 JSON 格式来返回数据：

{
    identifier: '<name>',
    <label: '<label>',>
    items: [
        { name: '...', label: '...', someKey: '...' },
        ...
    ]
}

Zend_Dojo_Data 提供一个简单的接口通过程序来构造这样的结构， 交互并系列化成一个数组或 JSON。

Zend_Dojo_Data 用法

很简单，dojo.data 要求你在每个条目和一组条目（数据）中提供标识符字段的名字。 你可以通过构造函数或 mutators 来传递它们：

Example #1 通过构造函数初始化 Zend_Dojo_Data

$data = new Zend_Dojo_Data('id', $items);

Example #2 通过 mutators 初始化 Zend_Dojo_Data

$data = new Zend_Dojo_Data();
$data->setIdentifier('id')
     ->addItems($items);

用 addItem() 和 addItems() 添加一个单个条目或追加多个条目。

Example #3 追加数据到 Zend_Dojo_Data

$data = new Zend_Dojo_Data($identifier, $items);
$data->addItem($someItem);

$data->addItems($someMoreItems);

Note: 永远使用标识符！
 每个 dojo.data 数据存储要求以元数据来提供标识符列，Zend_Dojo_Data 也一样。 实际上，如果不用标识符添加条目，将会抛出异常。

条目可以是下列其中之一：

  • 联合数组

  • 实现 toArray() 方法的对象

  • 任何其它对象（将通过 get_object_vars() 系列化 ）

你可以通过 addItems() 或 setItems()（覆盖先前的条目） 附加上述条目的集合； 用的时候，你可以传递一个参数：

  • 数组

  • 实现Traversable接口的对象（包括 Iterator 和 ArrayAccess 接口）。

如果想为条目指定一个用作标签的字段，调用setLabel():

Example #4 在 Zend_Dojo_Data 里指定一个标签字段

$data->setLabel('name');

最后，你也可以用 fromJson() 方法从 dojo.data JSON 数组加载一个 Zend_Dojo_Data 条目，

Example #5 从 JSON 组装 Zend_Dojo_Data

$data->fromJson($json);

高级用例

除了可以作为可系列化的数据容器，Zend_Dojo_Data 也可以用各种各样的方法处理和疏导（traverse）数据。

Zend_Dojo_Data 实现 ArrayAccess、 Iterator 和 Countable 的接口。 这意味着你可以使用数据集合几乎就像使用数组一样。

所有的条目通过标识符字段来引用。因为表示符必须是独一无二的，你可用它的值来取出每个记录。 有两个方法可以做这个：通过 getItem() 方法，或通过数组符号。

// Using getItem():
$item = $data->getItem('foo');

// Or use array notation:
$item = $data['foo'];

如果你知道标识符，你可以用它来读取、更新、删除、创建或测试条目：

// Update or create an item:
$data['foo'] = array('title' => 'Foo', 'email' => 'foo@foo.com');

// Delete an item:
unset($data['foo']);

// Test for an item:
if (isset($data[foo])) {
}

你也可以遍历所有条目，在内部，所有的条目以数组形式存储。

foreach ($data as $item) {
    echo $item['title'] . ': ' . $item['description'] . "\n";
}

甚至还可以数出你有多少条目：

echo count($data), " items found!";

最后，因为这个类实现 __toString()， 你也可以通过 echo 它把它传给 JSON 或 字符串：

echo $data; // echo as JSON string

$json = (string) $data; // cast to string == cast to JSON

可用的方法

除了上述实现接口必须的方法外，下列方法也可用。

  • setItems($items): 一次设置多个条目，覆盖在对象里先前的任何条目。 $items 是一个数组或一个 Traversable 对象。

  • setItem($item, $id = null): 设置一个条目，可选地传递一个显式标识符。 如果有的话，覆盖先前在集合里的条目。有效的条目包括联合数组，实现 toArray() 的对象或任何有 public 属性的对象。

  • addItem($item, $id = null): 添加一个条目，可选地传递一个显式标识符。 如果在集合理已经存在该条目，将产生异常。有效的条目包括联合数组，实现 toArray() 的对象或任何有 public 属性的对象。

  • addItems($items): 一次添加多个条目，追加到任何当前条目。如果新条目的标识符在集合理已经存在，将产生异常。 $items 是一个数组或一个 Traversable 对象。

  • getItems(): 以数组的数组（array of arrays）的形式获取所有条目。

  • hasItem($id): 确定一个条目的标识符是否在集合理存在。

  • getItem($id): 从集合里按给定的标识符获取一个条目；返回一个联合数组。 如果没有条目匹配，返回 null。

  • removeItem($id): 从集合里按给定的标识符删除一个条目。

  • clearItems(): 从集合里删除所有条目。

  • setIdentifier($identifier): 为集合里的每个条目设置表示独一无二的标识符的字段名。

  • getIdentifier(): 获取标识符字段的名字。

  • setLabel($label): 设置用于为条目显示标签的字段的名字。

  • getLabel(): 读取标签字段名。

  • toArray(): 传递对象到一个数组。数组里最少包含键 'identifier' 和 'items'， 如果在对象里设置了标签，也要包含 'label'。

  • toJson(): 传递对象给一个JSON 表达。

简介
Zend_Dojo
Zend Framework手册 中文版
Dojo 视图助手
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Dojo
  • 简介
  • Zend_Dojo_Data: dojo.data Envelopes
  • Dojo 视图助手
  • Dojo 表单元素和装饰器
  • Zend_Dojo build layer support


Dojo 视图助手 - Zend Framework Manual

Zend_Dojo_Data: dojo.data Envelopes
Zend_Dojo
Zend Framework手册 中文版
Dojo 表单元素和装饰器

Dojo 视图助手

Zend Framework 提供下列 Dojo-specific 视图助手：

  • dojo(): 给你的页面设置 Dojo 环境， 包括 dojo 配置值、定制模块路径、模块请求语句、主题风格、是否使用 CDN 等等。

Example #1 使用 Dojo 视图助手

为了使用 Dojo 视图助手，你需要告诉视图对象到哪里去找它们，调用 addHelperPath()：

$view->addHelperPath('Zend/Dojo/View/Helper/', 'Zend_Dojo_View_Helper');

另外，你也可以使用 Zend_Dojo 的 enableView() 方法来做：

Zend_Dojo::enableView($view);

dojo() 视图助手

dojo() 视图助手用来简化设置 Dojo 环境，包括下列职责:

  • 指定一个 CDN 或一个本地路径给 Dojo 安装。

  • 指定路径给定制的 Dojo 模块。

  • 指定 dojo.require 语句。

  • 指定 dijit 风格主题来使用。

  • 指定 dojo.addOnLoad() 事件。

dojo() 视图助手实现是占位符实现的一个范例；数据集在视图对象之间持久， 并可能从布局脚本被直接显示。

Example #2 dojo() 视图助手用法范例

对本范例，假设开发者将从本地路径使用 Dojo 表单，需要请求若干个 dijits， 并将使用 Tundra dijit 主题。

在许多页面上，开发者可能根本不使用 Dojo。所以，我们集中精力在需要 Dojo 的视图脚本上， 然后是布局脚本，在那里，我们将设置一个 Dojo 环境和解析它。

首先，我们需要告诉视图对象使用 Dojo 视图助手路径。这可以在引导文件里或早期运行的插件里做； 简单地抓取你的视图对象并执行下列代码：

$view->addHelperPath('Zend/Dojo/View/Helper/', 'Zend_Dojo_View_Helper');

接着是视图脚本。在本例中，我们打算指定使用 FilteringSelect － 它需要基于 QueryReadStore 的定制的存储， 我们将调用 'PairedStore' 并存储到我们的 'custom' 模块。

<? // setup data store for FilteringSelect ?>
<div dojoType="custom.PairedStore" jsId="stateStore"
    url="/data/autocomplete/type/state/format/ajax"
    requestMethod="get"></div>

<? // Input element: ?>
State: <input id="state" dojoType="dijit.form.FilteringSelect"
    store="stateStore" pageSize="5" />

<? // setup required dojo elements:
$this->dojo()->enable()
             ->setDjConfigOption('parseOnLoad', true)
             ->registerModulePath('../custom/')
             ->requireModule('dijit.form.FilteringSelect')
             ->requireModule('custom.PairedStore');

在布局脚本中，我们接着检查是否开启了 Dojo，如果是，我们将做一些基本配置和组装：

<?= $this->doctype() ?>
<html>
<head>
    <?= $this->headTitle() ?>
    <?= $this->headMeta() ?>
    <?= $this->headLink() ?>
    <?= $this->headStyle() ?>
<? if ($this->dojo()->isEnabled()):
    $this->dojo()->setLocalPath('/js/dojo/dojo.js')
                 ->addStyleSheetModule('dijit.themes.tundra');
    echo $this->dojo();
?>
    <?= $this->headScript() ?>
</head>
<body class="tundra">
    <?= $this->layout()->content ?>
    <?= $this->inlineScript() ?>
</body>
</html>

在这点上，你只需要确保你的文件在正确的位置并且你已经为 FilteringSelect 创建了终点动作！

Dojo 的 Programmatic 和 Declarative 用法

Dojo 在其许多功能上使用 declarative 和 programmatic。 Declarative 用法使用标准的带有当页面加载时解析的非标准属性的 HTML 元素。 虽然强大并且语法简单，对大多数开发者来说，它在页面校验时容易出问题。

Programmatic 用法让开发者通过用ID或 CSS 选择器把它们来出来并解析 到合适的在 Dojo 里的对象构造器来装饰存在的元素。因为没有使用非标准 HTML 属性，页面可以继续校验。

在实践中，当禁止 javascript 或不能获取部分 Dojo 脚本资源，上述两个用例都考虑了完美的降级。 为提升标准和文档校验， Zend Framework 缺省使用 programmatic 用法，各种 视图助手将生成 javascript 并压到 dojo() 视图助手，在解析时包含。

用这个技术的开发者可能也想探索写自己的页面 programmatic 装饰器。 一个好处是可以指定 dijit 事件的句柄。

为使用此功能，同时也使用 declarative 语法，有许多静态方法可以全局使用。

Example #3 指定 Declarative 和 Programmatic Dojo 用法范例

为指定 declarative 用法，简单地调用静态方法 setUseDeclarative()：

Zend_Dojo_View_Helper_Dojo::setUseDeclarative();

如果你决定使用 programmatic 用法，调用静态方法 setUseProgrammatic()：

Zend_Dojo_View_Helper_Dojo::setUseProgrammatic();

最后，如果你想生成自己的 programmatic 规则，你应当指定 programmatic 用法， 但是传递值 '-1'；在这种情况下，不生成用于装饰 dijit 的 javascript。

Zend_Dojo_View_Helper_Dojo::setUseProgrammatic(-1);

主题

Dojo 允许为它的 dijits（小部件）生成主题。你可以通过传递模块路径来选择一个：

$view->dojo()->addStylesheetModule('dijit.themes.tundra');

模块路径通过使用字符 '.'作为目录分隔符和在主题目录里列表中最后的值作为CSS文件的名称来找出。 在上述例子中，Dojo 在 'dijit/themes/tundra/tundra.css' 中寻找主题。

当使用主题时，记住传递主题类很重要，至少，传递在你使用的 dijits 周围的容器； 最常用的用例是在 body 里传递它：

<body class="tundra">

使用 Layers （定制）

缺省地，当你使用 dojo.require 语句，dojo 将请求服务器抓取适当的 javascript 文件。 如果你有许多 dijits ，将导致许多对服务器请求，－ 这不是很理想。

Dojo 的解决方案是提供生成 定制 的能力，定制做如下事情：

  • 把请求文件集中到 layers，layer 把所有的请求 文件集中成一个单个的 JS 文件。（Hence the name of this section.）

  • "Interns" non-javascript files used by dijits (typically, template files). These are also grouped in the same JS file as the layer.

  • 通过 ShrinkSafe 传递文件，它剥离了空白字符和注释，还缩短了短变量名。

有些文件不能被 layered，但定制处理将生成一个特别的目录来放 layer 文件和其它所有文件。 这会对你的站点或应用需求减少发行定制。

为了使用 layer，dojo() 视图助手有一个 addLayer() 方法来添加路径到请求 layers:

$view->dojo()->addLayer('/js/foo/foo.js');

更多关于生成定制的信息，请 » refer 参考 Dojo 构造文档.

可用方法

dojo() 视图助手总返回 dojo 占位符容器的实例。 这容器对象有下列方法可用：

  • setView(Zend_View_Interface $view): 在容器中设置一个视图实例。

  • enable(): 显式地开启 Dojo 集成。

  • disable(): 关闭 Dojo 集成。

  • isEnabled(): 确定是否 Dojo 集成已经开启。

  • requireModule($module): 设置一条 dojo.require 语句。

  • getModules(): 确定模块 已经被请求。

  • registerModulePath($module, $path): 注册一个定制的 Dojo 模块路径。

  • getModulePaths(): 获得已注册模块路径列表。

  • addLayer($path): 添加一个 layer （定制） 路径。

  • getLayers(): 获得已注册的 layer 路径（定制）的列表。

  • removeLayer($path): 从已注册的 layers （定制）列表里删除匹配 $path 的 layer。

  • setCdnBase($url): 为 CDN 设置基础 URL； 一般地是 Zend_Dojo::CDN_BASE_AOL 或 Zend_Dojo::CDN_BASE_GOOGLE 其中之一， 但它只需要在版本号之前的 URL 字符串。

  • getCdnBase(): 获取基础 CDN url

  • setCdnVersion($version = null): 从 CDN 设置 Dojo 的版本。

  • getCdnVersion(): 从将要用的 CDN 获取 Dojo 的版本。

  • setCdnDojoPath($path): 在一个 CDN 中设置 dojo.js 或 dojo.xd.js 文件的相对路径 ； 一般地是 Zend_Dojo::CDN_DOJO_PATH_AOL 或 Zend_Dojo::CDN_DOJO_PATH_GOOGLE 其中之一，但 它只需要是带版本号的路径字符串。

  • getCdnDojoPath(): 获取最后的 CDN url 指向 dojo.js文件的路径段。

  • useCdn(): 告诉容器使用 CDN；显式地开启集成。

  • setLocalPath($path): 告诉容器指向本地 Dojo 安装（和服务器相关的路径，包括 dojo.js 文件自己） 的路径。显式地开启集成。

  • getLocalPath(): 确定使用哪个本地 Dojo 路径。

  • useLocalPath(): 是否集成使用 Dojo 本地路径？

  • setDjConfig(array $config): 设置 dojo/dijit 配置值（需要联合数组）。

  • setDjConfigOption($option, $value): 设置一单个的 dojo/dijit 配置值。

  • getDjConfig(): 获取所有的 dojo/dijit 配置值。

  • getDjConfigOption($option, $default = null): 获取一单个的 dojo/dijit 配置值。

  • addStylesheetModule($module): 基于模块主题添加风格。

  • getStylesheetModules(): 获取注册为模块主题的风格。

  • addStylesheet($path): 添加一个本地风格来和 Dojo 一起使用。

  • getStylesheets(): 获取本地 Dojo 风格。

  • addOnLoad($spec, $function = null): 为 dojo.onLoad 添加一个 lambda 来调用。如果传递一个参数，那就是 函数名或一个 javascript closure。如果传递两个参数，第一参数是 对象实例变量的名字，第二个参数是该对象的方法名或使用这个对象的 一个 closure。

  • getOnLoadActions(): 获取所有用容器注册的 dojo.onLoad 动作，将是一个数组的数组。

  • onLoadCaptureStart($obj = null): 为 dojo.onLoad() 抓取用做 lambda 的数据。如果提供了 $obj， 那么 JS 抓取代码被认为是一个和 Javascript 对象一起使用的 closure 。

  • onLoadCaptureEnd($obj = null): 停止为使用 dojo.onLoad() 抓取数据。

  • javascriptCaptureStart(): 抓取任意的 javascript 包含到 Dojo JS （onLoad、 require 等语句）。

  • javascriptCaptureEnd(): 停止抓取 javascript。

  • __toString(): 转换容器为字符串；解析所有的 HTMl 风格和脚本元素。

Dijit-Specific 视图助手

引用一下 Dojo 手册：“Dijit 是基于 dojo 之上的一个小部件系统”，Dijit 有 许多布局和表单小部件，用来提供访问、本地化和标准化（和可主题化）的观感。

Zend Framework 带有许多视图助手让你在视图脚本里解析和使用 dijits。有三个基本类型：

  • 布局容器: 这些设计上在视图脚本理使用或由表单装饰器用于表单、子表单和显示组。 它们封装了 dijit.layout 提供的各种类。每个 dijit 布局视图助手有下面的参数：

    • $id: 容器名或 DOM ID。

    • $content: 在布局容器里封装的内容。

    • $params (optional): dijit-specific 参数。 基本上是任何非 HTML 属性，可用于配置 dijit 布局容器。

    • $attribs （可选）：任何用于解析容器 div 的附加的 HTML 属性。 如果在这个数组里传递了键 'id'，它将被用于表单元素 DOM id，并且 $id 将用于它的名字。

    如果不传递参数给 dijit 布局视图助手，那么助手将返回自己。 它允许你抓取内容，通常是更容易的传递内容给布局容器的方法。 本章的后面将用范例来示范这个功能。

  • Form Dijit: dijit.form.Form dijit，虽然对于使用 dijit 表单元素不是完全必要，但是它可以确保如果提交没有根据客户端校验而校验的表单时， 提交就被终止并且产生校验错误消息。该表单 dijit 视图助手可带有下列参数：

    • $id: 容器名或 DOM ID。

    • $attribs （可选）：任何用于解析容器 div 的附加的 HTML 属性。

    • $content （可选）：要封装到表单的内容。如果没有，将使用空的字符串。

    为了和标准的 form() 视图助手保持兼容，参数顺序和其它 dijit 有些不同。

  • 表单元素 ：设计上和 Zend_Form 一起使用，但也 可以在视图脚本中独立使用。每个 dijit 元素视图助手可以使用下列参数：

    • $id: 元素名或 DOM ID。

    • $value （可选）：元素的当前值。

    • $params （可选）： dijit-specific 参数。 基本上是任何用于配置 dijit 的非 HTML 属性。

    • $attribs （可选）：任何用于解析 dijit的附加的 HTML 属性。 如果键 'id' 在这个数组中传递，它将被用于表单元素的 DOM id， 并且 $id 将被用于它的名字。

    一些元素要求更多的参数，将在个别元素助手的描述中注明。

为了使用这些视图助手，你需要用视图对象来注册路径给 dojo 视图助手。

Example #4 注册 Dojo 视图助手前缀路径

$view->addHelperPath('Zend/Dojo/View/Helper', 'Zend_Dojo_View_Helper');

Dijit 布局元素

dijit.layout 元素家族用来生成定制的、可预计的布局。任何关于用法的问题 » 请阅读 Dojo 手册。

所有的 dijit 布局元素都有签名 string ($id = null, $content = '', array $params = array(), array $attribs = array())。 对于所有情况，如果不传递参数，就返回助手对象自己。 访问 captureStart() 和 captureEnd() 方法，它让你 抓取内容而不是传递它给布局容器。

  • AccordionContainer：dijit.layout.AccordionContainer。 垂直堆放所有的 pane ，点击一个 pane 的 titlebar 就会展开并显示特定的 pane。

    <?= $view->accordionContainer(
    'foo',
    $content,
    array(
        'duration' => 200,
    ),
    array(
        'style' => 'width: 200px; height: 300px;',
    ),
); ?>

  • AccordionPane: dijit.layout.AccordionPane. 在 AccordionContainer 内使用。

    <?= $view->accordionPane(
    'foo',
    $content,
    array(
        'title' => 'Pane Title',
    ),
    array(
        'style' => 'background-color: lightgray;',
    ),
); ?>

  • BorderContainer：dijit.layout.BorderContainer。 用象传统程序中的可改变尺寸的 pane 来完成布局。

    <?= $view->borderContainer(
    'foo',
    $content,
    array(
        'design' => 'headline',
    ),
    array(
        'style' => 'width: 100%; height: 100%',
    ),
); ?>

  • ContentPane: dijit.layout.ContentPane。 用在除了 AccordionContainer 以外的任何容器内部。

    <?= $view->contentPane(
    'foo',
    $content,
    array(
        'title'  => 'Pane Title',
        'region' => 'left',
    ),
    array(
        'style' => 'width: 120px; background-color: lightgray;',
    ),
); ?>

  • SplitContainer：dijit.layout.SplitContainer。 允许可变尺寸的内容 pane；在 Dojo 里废除转而使用 BorderContainer。

    <?= $view->splitContainer(
    'foo',
    $content,
    array(
        'orientation'  => 'horizontal',
        'sizerWidth'   => 7,
        'activeSizing' => true,
    ),
    array(
        'style' => 'width: 400px; height: 500px;',
    ),
); ?>

  • StackContainer：dijit.layout.StackContainer。 所有在 StackContainer 里的 pane 放在一个堆栈里，生成按钮或功能一次显示一个。

    <?= $view->stackContainer(
    'foo',
    $content,
    array(),
    array(
        'style' => 'width: 400px; height: 500px; border: 1px;',
    ),
); ?>

  • TabContainer：dijit.layout.TabContainer。 所有在 TabContainer 里的 pane 放在一个堆栈里，并带有 tab 的位置，用于切换。

    <?= $view->stackContainer(
    'foo',
    $content,
    array(),
    array(
        'style' => 'width: 400px; height: 500px; border: 1px;',
    ),
); ?>

下列的抓取方法对所有的布局容器都可用：

  • captureStart($id, array $params = array(), array $attribs = array())： 开始抓取内容到容器。$params 是和容器一起使用的 dijit 参数， $attribs 指的是任何一般的 HTML 属性。

    只要 ids 没有重复 ，容器在抓取的时候可以嵌套。

  • captureEnd($id)： 完成抓取内容到容器。$id 是指先前和 captureStart() 调用一起使用的 id。返回一个字符串表示容器和它的内容，就好像传递内容给助手自己。

Example #5 BorderContainer 布局 dijit 范例

BorderContainers, 特别是当和抓取内容耦合时，对复杂的布局效果特别有用。

$view->borderContainer()->captureStart('masterLayout', array('design' => 'headline'));

echo $view->contentPane(
    'menuPane',
    'This is the menu pane',
    array('region' => 'top'),
    array('style' => 'background-color: darkblue;')
);

echo  $view->contentPane(
    'navPane',
    'This is the navigation pane',
    array('region' => 'left'),
    array('style' => 'width: 200px; background-color: lightblue;')
);

echo $view->contentPane(
    'mainPane',
    'This is the main content pane area',
    array('region' => 'center'),
    array('style' => 'background-color: white;')
);

echo $view->contentPane(
    'statusPane',
    'Status area',
    array('region' => 'bottom'),
    array('style' => 'background-color: lightgray;')
);

echo $view->borderContainer()->captureEnd('masterLayout');

Dijit 表单元素

Dojo 的表单校验和输入 dijit 在 dijit.form 树中。 更多关于这些元素的一般用法和可接受的参数，请 » 访问 dijit.form 文档.

下列 dijit 表单元素在 Zend Framework 里可用。 除非注明，都有签名 string ($id, $value = '', array $params = array(), array $attribs = array()).

  • Button: dijit.form.Button. 显示一个表单按钮

    <?= $view->button(
    'foo',
    'Show Me!',
    array('iconClass' => 'myButtons'),
); ?>

  • CheckBox：dijit.form.CheckBox. 显示一个 checkbox。接受可选的第五个参数，$checkedOptions 数组， 包含：

    • 按顺序带两个值的索引数组，一个选中的值和一个未选中的值；或者

    • 带键 'checkedValue' 和 'unCheckedValue'的联合数组。

    如果没有提供 $checkedOptions 就假定为 1 和 0 。

    <?= $view->checkBox(
    'foo',
    'bar',
    array(),
    array(),
    array('checkedValue' => 'foo', 'unCheckedValue' => 'bar')
); ?>

  • ComboBox：dijit.layout.ComboBox. 组合框是一个混合体，包括选择框和带有自动完成的文字框。 关键是在列表里没有相应的选项的时候可以手工输入，而且是有效的。 它接受可选的第五个参数：联合数组 $options；如果提供 了该参数，ComboBox 就当作 select 被解析。也要注意 $options 数组的 标签值 在表单中返回， 而不选项值自己。

    另外，也可以传递关于和元素一起使用的 dojo.data 数据存储的信息。 如果提供该参数，ComboBox 就当作 input 被解析， 并且将通过那个数据存储来取出它的选项。

    为了指定数据存储，请提供下列 $params 键组合之一：

    • 键 'store'，带有一个数组值；数组应包含下列键：

      • store：表示数据存储的 javascript 变量名 （this could be the name you would like for it to use）。

      • type：数据存储类型；例如：'dojo.data.ItemFileReadStore'。

      • params （可选）：一个键/值对的联合数组，用来配置数据存储。 'url' 参数是个典型的例子。

    • 键：

      • store：表示数据存储名的字符串。

      • storeType：表示数据存储 dojo.data 类型的字符传（例如 'dojo.data.ItemFileReadStore'）。

      • storeParams：一个键/值对联合数组，用于配置数据存储。

    // As a select element:
echo $view->comboBox(
    'foo',
    'bar',
    array(
        'autocomplete' => false,
    ),
    array(),
    array(
        'foo' => 'Foo',
        'bar' => 'Bar',
        'baz' => 'Baz',
    )
);

// As a dojo.data-enabled element:
echo $view->comboBox(
    'foo',
    'bar',
    array(
        'autocomplete' => false,
        'store'        => 'stateStore',
        'storeType'    => 'dojo.data.ItemFileReadStore',
        'storeParams'  => array('url' => '/js/states.json'),
    ),
);

  • CurrencyTextBox：dijit.form.CurrencyTextBox。 从 ValidationTextBox 继承，并提供货币的客户端校验。 它期望 dijit 参数 'currency' 的值是适当的三字符货币代码。 可以为 ValidationTextBox 和 TextBox 指定任何有效的 dijit 参数。

    echo $view->currencyTextBox(
    'foo',
    '$25.00',
    array('currency' => 'USD'),
    array('maxlength' => 20)
);

    Note: Issues with Builds
     目前有这些 » 和 build 层一起使用的 CurrencyTextBox 的已知问题 . 一个解决办法是确保文档的 Content-Type http-equiv meta tag 把字符集设置为 utf-8， 可通过调用下列方法来完成：

    $view->headMeta()->appendHttpEquiv('Content-Type', 'text/html; charset=utf-8');
?>
    这当然意味着你需要确保 headMeta() 占位符在布局脚本中。

  • DateTextBox：dijit.form.DateTextBox. 从 ValidationTextBox 继承，提供客户端的日期校验和下拉式日历。 你可以指定任何 dijit 可用的参数给 ValidationTextBox 或 TextBox。

    echo $view->dateTextBox(
    'foo',
    '2008-07-11',
    array('required' => true)
);

  • FilteringSelect：dijit.form.FilteringSelect。 和 ComboBox 类似，这是个选择/文字混合体，它可以从提供的选项列表 里读取或者从 dojo.data 数据存储里抓取。和 ComboBox 不一样的地方是 FilteringSelect 不允许输入不在列表里的选项。另外，它的操作和标准选择 一样，从选项值里选择而不是从标签里选择，当表单提交时返回它们。

    请参考上述关于 ComboBox 范例和定义数据存储的可用选项的信息。

  • HorizontalSlider 和 VerticalSlider： dijit.form.HorizontalSlider 和 dijit.form.VerticalSlider. 滑尺是 UI 小部件，用来在给定范围内选择数值的，这两个一个是水平的，一个是垂直的。

    至少，它们需要 dijit 参数 'minimum'、 'maximum' 和 'discreteValues'，来定义值的范围。 其它通用的选项有：

    • 'intermediateChanges' 用来表明当 handle 被拖的时候是否需要发出 onChange 事件。

    • 'clickSelect' 用来允许在滑尺上点击来设置其值。

    • 'pageIncrement' 通过 pageUp 和 pageDown 来增加/减少值。

    • 'showButtons' 设置来允许在滑尺的一端显示按钮来操作数值。

    Zend Framework 实现生成一个隐藏的元素来存储滑尺的数值。

    你可以可选地为滑尺显示尺子或标签，可通过分配一个或多个 dijit 参数 'topDecoration' 和/或 'bottomDecoration'(水平滑尺） 或 'leftDecoration' 和/或 'rightDecoration' （垂直滑尺）来完成。它们有下列选项：

    • container：容器名称。

    • labels （可选）：标签数组。 在滑尺的一端使用空字符串只为内部值提供标签。 当指定一个 'Labels' dijit 变量时必需。

    • dijit （可选）： HorizontalRule、HorizontalRuleLabels、 VerticalRule 或 VerticalRuleLabels 中的一个，缺省为尺子 dijits 之一。

    • params （可选）： 配置尺子 dijit 的 dijit 参数，参数规范包括：

      • container （可选）： 尺子容器的属性和参数的数组。

      • labels （可选）： 标签列表容器的属性和参数的数组。

    • attribs （可选）： 和尺子/标签一起使用的 HTML 属性，遵循 params 选项格式并 且是一个带有键 'container' 和 'labels' 的联合数组。

    echo $view->horizontalSlider(
    'foo',
    1,
    array(
        'minimum'             => -10,
        'maximum'             => 10,
        'discreteValues'      => 11,
        'intermediateChanges' => true,
        'showButtons'         => true,
        'topDecoration'       => array(
            'container' => 'topContainer'
            'dijit'     => 'HorizontalRuleLabels',
            'labels'    => array(
                ' ',
                '20%',
                '40%',
                '60%',
                '80%',
                ' ',
            ),
            'params' => array(
                'container' => array(
                    'style' => 'height:1.2em; font-size=75%;color:gray;',
                ),
                'labels' => array(
                    'style' => 'height:1em; font-size=75%;color:gray;',
                ),
            ),
        ),
        'bottomDecoration'    => array(
            'container' => 'bottomContainer'
            'labels'    => array(
                '0%',
                '50%',
                '100%',
            ),
            'params' => array(
                'container' => array(
                    'style' => 'height:1.2em; font-size=75%;color:gray;',
                ),
                'labels' => array(
                    'style' => 'height:1em; font-size=75%;color:gray;',
                ),
            ),
        ),
    )
);

  • NumberSpinner：dijit.form.NumberSpinner。 数字输入文本框，按钮用来增减值。

    期望用于 dijit 参数 'constraints' 的联合数值或者键 'min'、'max' 和 'places' （这些也期望 constraints 参数的条目）。 'places' 可用于指示微调数的增加和减少的数值。

    echo $view->numberSpinner(
    'foo',
    5,
    array(
        'min'    => -10,
        'max'    => 10,
        'places' => 2,
    ),
    array(
        'maxlenth' => 3,
    )
);

  • NumberTextBox：dijit.form.NumberTextBox。 NumberTextBox 可选地依靠给定的限制以本地化方式格式化和显示数字条目，同时也校验数字条目。

    echo $view->numberTextBox(
    'foo',
    5,
    array(
        'places' => 4,
        'type'   => 'percent',
    ),
    array(
        'maxlength' => 20,
    )
);

  • PasswordTextBox： 和密码输入相关的 dijit.form.ValidationTextBox。 PasswordTextBox 生成密码输入，并和当前的 dijit 主题匹配，同时也做客户端校验。

    echo $view->passwordTextBox(
    'foo',
    '',
    array(
        'required' => true,
    ),
    array(
        'maxlength' => 20,
    )
);

  • RadioButton：dijit.form.RadioButton。 一组选项，但只能选一个，除了视觉上和其它 dijits 保持一致， 其它方面都和普通的单选（radio，也叫无线电按钮）元素一样。

    RadioButton 接受可选的第五个参数，$options， 是个联合数组，值/标签对用作radio选项。 你可以以 $attribs 键 options 来传递。

    echo $view->radioButton(
    'foo',
    'bar',
    array(),
    array(),
    array(
        'foo' => 'Foo',
        'bar' => 'Bar',
        'baz' => 'Baz',
    )
);

  • SubmitButton：和提交元素相关的 dijit.form.Button。 参见按钮视图助手有更多的细节。主要的区别是这个按钮可以提交一个表单。

  • Textarea：dijit.form.Textarea. 除了有很多行以外，和普通的文本区域一样，它们按照用户类型来扩展。 宽度通过风格来设定。

    echo $view->textarea(
    'foo',
    'Start writing here...',
    array(),
    array('style' => 'width: 300px;')
);

  • TextBox：dijit.form.TextBox。 该元素主要用来在不同的 dijit 元素之间提供一个通用的外观， 并对其它 TextBox 派生的类 （ValidationTextBox、 NumberTextBox、 CurrencyTextBox、 DateTextBox 和 TimeTextBox）提供基本功能。

    普通的 dijit 参数标志包括 'lowercase' （转换成小写）、 'uppercase' （转换成大写）、 'propercase' （转换成合适的大小写）和 trim （修剪引导和拖尾的空白字符）； 它们都接受布尔值。另外，你可以指定参数 'size' 和 'maxLength'。

    echo $view->textBox(
    'foo',
    'some text',
    array(
        'trim'       => true,
        'propercase' => true,
        'maxLength'  => 20,
    ),
    array(
        'size' => 20,
    )
);

  • TimeTextBox： dijit.form.TimeTextBox。 也包含在 TextBox 家族，TimeTextBox 提供一个下拉式时间选择器。 Dijit 参数让你指定可用的时间增量以及有效的时间的可见范围。

    echo $view->timeTextBox(
    'foo',
    '',
    array(
        'am.pm'            => true,
        'visibleIncrement' => 'T00:05:00', // 5-minute increments
        'visibleRange'     => 'T02:00:00', // show 2 hours of increments
    ),
    array(
        'size' => 20,
    )
);

  • ValidationTextBox：dijit.form.ValidateTextBox。 为文本元素提供客户端校验。从 TextBox 继承。

    普通的 dijit 参数包括：

    • invalidMessage：当检测到一个无效的输入，就显示一条消息。

    • promptMessage：工具提示帮助信息。

    • regExp：用于校验文本的正则表达式，不需要边界记号。

    • required：确定元素是否必需。如果需要就把元素嵌入 dijit.form.Form，它将被标记为无效并防止提交。

    echo $view->validationTextBox(
    'foo',
    '',
    array(
        'required' => true,
        'regExp'   => '[\w]+',
        'invalidMessage' => 'No spaces or non-word characters allowed',
        'promptMessage'  => 'Single word consisting of alphanumeric characters and underscores only',
    ),
    array(
        'maxlength' => 20,
    )
);
Zend_Dojo_Data: dojo.data Envelopes
Zend_Dojo
Zend Framework手册 中文版
Dojo 表单元素和装饰器
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Dojo
  • 简介
  • Zend_Dojo_Data: dojo.data Envelopes
  • Dojo 视图助手
  • Dojo 表单元素和装饰器
  • Zend_Dojo build layer support


Dojo 表单元素和装饰器 - Zend Framework Manual

Dojo 视图助手
Zend_Dojo
Zend Framework手册 中文版
Zend_Dojo build layer support

Dojo 表单元素和装饰器

建立在 dijit 视图助手 之上的 Zend_Dojo_Form 类家族在你的表单里自然地使用 Dijits。

有三个选项用来在你的表单里使用 Dojo 表单元素：

  • 用 Zend_Dojo::enableForm(). 递归地为装饰器和所有表单的元素添加插件路径。 另外，它将 dojo-enable 视图对象。然而注意，任何在这个调用 之后 附加 的子表单也需要用 Zend_Dojo::enableForm()。

  • 分别使用 Dojo-specific 表单Zend_Dojo_Form和子表单 Zend_Dojo_Form_SubForm实现。 这些可以做为 Zend_Form 和 Zend_Form_SubForm的随时替换，包含所有合适的装饰器 和元素路径，设置一个 Dojo-specific 缺省的显示组类并 dojo-enable 视图。

  • 最后并且是最单调的是，你可以自己设置合适的装饰器和元素路径，设置缺省显示组类 并 dojo-enable 视图。因为 Zend_Dojo::enableForm() 已经做了这个， 有个小原因需要这样做。

Example #1 在你的表单里开启 Dojo

“等等” 你会说，“我已经用我自己定制的表单类扩展了 Zend_form！怎么 Dojo-enable 它？”

首先而且是最简单的是，修改从 Zend_Form 扩展为从 Zend_Dojo_Form 扩展， 并更新任何实例化 Zend_Form_SubForm 的地方为实例化 Zend_Dojo_Form_SubForm。

第二个方法是在定制表单的 init() 方法里调用 Zend_Dojo::enableForm()； 当表单定义完成，遍历所有子表单来 dojo-enable 它们：

class My_Form_Custom extends Zend_Form
{
    public function init()
    {
        // Dojo-enable the form:
        Zend_Dojo::enableForm($this);

        // ... continue form definition from here

        // Dojo-enable all sub forms:
        foreach ($this->getSubForms() as $subForm) {
            Zend_Dojo::enableForm($subForm);
        }
    }
}

dijit-specific 表单装饰器和元素的用法和使用任何其它表单装饰漆或元素一样。

Dijit-Specific 表单装饰器

大多数表单元素可以使用 DijitElement 装饰器，它从元素抓取 dijit 参数， 然后和其它元数据一起传递给由元素指定的视图助手。对于装饰表单、子表单和显示组， 有一组和不同的布局 dijits 对应的装饰器。

所有的 jijit 装饰器寻找给定被装饰元素的 dijitParams 属性， 并把它们压到 $params 数组传递给被使用的 dijit 视图助手； 这些就和其它属性分离，这样就不会有重复的信息。

DijitElement 装饰器

就像 视图助手装饰器， DijitElement 也在元素里有个 helper 属性，解析时，它将被用作视图助手。 Dijit 参数将直接从元素理拉出来，但也可能通过 dijitParams 键（键值应当是个联合数组选项） 作为选项被传递。

每个元素有个独一无二的 ID （从元素的getId()方法读出）很重要。 如果在 dojo() 视图助手里检测到重复的 ID，装饰器将触发一个提示， 接着通过追加 uniqid() 的返回值到标识符来生成一个独一无二的 ID。

标准用法是在装饰器链附加这个装饰器为第一个装饰器，不需要另外的选项。

Example #2 DijitElement 装饰器用法

$element->setDecorators(array(
    'DijitElement',
    'Errors',
    'Label',
    'ContentPane',
));

DijitForm 装饰器

DijitForm 装饰器和 表单装饰器 非常类似；事实上，它们可以交互使用，因为它们使用同样的视图助手名（'form'）。

因为 dijit.form.Form 不要求任何 dijit 参数来配置，主要的不同之处是 dijit 表单视图助手 要求传递一个 DOM ID 来确保程序生成 dijit。装饰器通过传递表单名为表示符来保证它。

DijitContainer-based 装饰器

DijitContainer 装饰器实际上是一个摘要类，其它装饰器都从它派生。它 提供了和 DijitElement 一样的功能， 并带有另外的标题支持。许多布局 dijits 要求或使用标题；如果可能，DijitContainer 将使用元素的 legend 属性，如果传递 它也可以使用 'legend' 或 'title'装饰器选项其中之一。如果有对应的翻译适配器，标题将被翻译。

下列的装饰器从 DijitContainer 继承：

  • AccordionContainer

  • AccordionPane

  • BorderContainer

  • ContentPane

  • SplitContainer

  • StackContainer

  • TabContainer

Example #3 DijitContainer 装饰器用法

// Use a TabContainer for your form:
$form->setDecorators(array(
    'FormElements',
    array('TabContainer', array(
        'id'          => 'tabContainer',
        'style'       => 'width: 600px; height: 500px;',
        'dijitParams' => array(
            'tabPosition' => 'top'
        ),
    )),
    'DijitForm',
));

// Use a ContentPane in your sub form (which can be used with all but
// AccordionContainer):
$subForm->setDecorators(array(
    'FormElements',
    array('HtmlTag', array('tag' => 'dl')),
    'ContentPane',
));

Dijit-Specific 表单元素

每个被提供视图助手的 dijit 表单都有相应的Zend_Form元素。它们都有下列方法来处理 dijit 参数：

  • setDijitParam($key, $value): 设置一单个的 dijit 参数。 如果 dijit 参数已经存在，则覆盖它。

  • setDijitParams(array $params): 一次设置若干 dijit 参数。 同样，已经存在的参数被覆盖。

  • hasDijitParam($key): 是否有个给定的 dijit 参数被定义和存在。

  • getDijitParam($key): 获取给定 $key 的 dijit 参数，如果不可用，则返回 null。

  • getDijitParams(): 获取所有的 dijit 参数。

  • removeDijitParam($key): 删除给定 $key 的 dijit 参数。

  • clearDijitParams(): 清除所有当前定义的 dijit 参数。

Dijit 参数存储在 dijitParams 公共属性里。这样，你可以 通过设置这个元素的属性来 dijit-enable 一个存在的表单元素。 你将不会有 上述访问器来简化处理这些参数。

另外，dijit-specific 元素实现一个不同的装饰器列表，相应如下：

$element->addDecorator('DijitElement')
        ->addDecorator('Errors')
        ->addDecorator('HtmlTag', array('tag' => 'dd'))
        ->addDecorator('Label', array('tag' => 'dt'));

实际上，DijitElement 装饰器用来替换标准的 ViewHelper 装饰器。

最后，基本的 Dijit 元素确保在视图中设置 Dojo 视图助手路径。

一个提供 多重 摘要表单元素的功能的 DijitElement 的变量 DijitMulti 让开发者指定 'multiOptions' － 一般是 select 选项或 radio 选项。

下列 dijit 元素随标准的 Zend Framework 版本发行。

按钮

虽然不是从 标准 Button 元素中派生， 它确实实现了相同的功能，并可以随时替换它。展示一下下列函数：

  • getLabel() 如果没有提供名字，将使用元素名作为按钮标签。另外， 如果翻译适配器有匹配的翻译信息，它将翻译这个名字。

  • isChecked() 确定是否提交的值和标签（label）匹配，如果匹配，返回true。 这对于当提交表单时确定用了那个按钮很有用。

另外，只有 DijitElement 和 DtDdWrapper 装饰器用于按钮元素。

Example #4 按钮 dijit 元素用法范例

$form->addElement(
    'Button',
    'foo',
    array(
        'label' => 'Button Label',
    )
);

检查框

虽然不是从 标准检查框元素 里派生， 但它确实实现了相同的功能。展示一下下列函数：

  • setCheckedValue($value): 设置一个值，当元素被选就用这个值。

  • getCheckedValue(): 获取当元素被时选使用的值。

  • setUncheckedValue($value): 设置一个值，当元素不被选中就用这个值。

  • getUncheckedValue(): 获取当元素不被选中时使用的值。

  • setChecked($flag): 标记元素为选中或未选中。

  • isChecked(): 确定元素是否被选中。

Example #5 检查框 dijit 元素用法范例

$form->addElement(
    'CheckBox',
    'foo',
    array(
        'label'          => 'A check box',
        'checkedValue'   => 'foo',
        'uncheckedValue' => 'bar',
        'checked'        => true,
    )
);

组合框（ComboBox）和 FilteringSelect

正如在组合框 dijit 视图助手文档 里的注释， 组合框是介于选择和文本输入之间的混合体，可以从列表中选择也可以输入内容到列表里。 FilteringSelect 也一样，但不允许任意输入。

Note: 组合框（ComboBoxes） 返回标签值
 组合框返回标签值而不是选项值，它可期望导致分离（disconnect）。 由于这个原因，组合框不自动注册一个 InArray 校验器（而 FilteringSelects 会）。

组合框和 FilteringSelect 表单元素提供访问器和增变器来检查和设置选择选项和指定 dojo.data 数据存储（如果使用的话）。 它们从 DijitMulti 继承，允许你通过 setMultiOptions() 和 setMultiOption() 方法指定选择选项。 另外，下列方法可用：

  • getStoreInfo(): 获取当前设置的所有数据存储信息，如果没有，返回一个空的数组。

  • setStoreId($identifier): 设置存储标识符变量（在 Dojo 里通常由属性 'jsId' 指定）。 这个应当是有效的 javascript 变量名。

  • getStoreId(): 获取存储标识符变量名。

  • setStoreType($dojoType): 设置数据存储类，例如"dojo.data.ItemFileReadStore"。

  • getStoreType(): 获取 dojo 数据存储类。

  • setStoreParams(array $params): 设置任何用于配置数据存储对象的参数。 例如，dojo.data.ItemFileReadStore 期望一个'url'参数指向一个能返回 dojo.data 对象的位置。

  • getStoreParams(): 获取任何当前设置的数据存储参数，如果没有，返回一个空数组。

  • setAutocomplete($flag): 标识当用户离开元素时，是否选择的条目将被使用。

  • getAutocomplete(): 获取自动完成标志的值。

缺省地，如果没有 dojo.data 存储和元素一起注册，该元素就注册 一个 InArray 校验器，它依靠注册的选项的数组键来校验。 你可以通过调用 setRegisterInArrayValidator(false) 或 传递一个 false 值给 registerInArrayValidator 配置键 来禁止该行为。

Example #6 使用组合框 dijit 元素做选择输入的范例

$form->addElement(
    'ComboBox',
    'foo',
    array(
        'label'        => 'ComboBox (select)',
        'value'        => 'blue',
        'autocomplete' => false,
        'multiOptions' => array(
            'red'    => 'Rouge',
            'blue'   => 'Bleu',
            'white'  => 'Blanc',
            'orange' => 'Orange',
            'black'  => 'Noir',
            'green'  => 'Vert',
        ),
    )
);

Example #7 带数据存储的组合框 dijit 元素用法范例

$form->addElement(
    'ComboBox',
    'foo',
    array(
        'label'       => 'ComboBox (datastore)',
        'storeId'     => 'stateStore',
        'storeType'   => 'dojo.data.ItemFileReadStore',
        'storeParams' => array(
            'url' => '/js/states.txt',
        ),
        'dijitParams' => array(
            'searchAttr' => 'name',
        ),
    )
);

上述例子也可以使用 FilteringSelect 来代替 ComboBox。

货币文字框

货币文字框主要用来支持货币输入。货币可以是本地化的，并且支持带小数的和不带小数的数值。

在内部，货币文字框由 NumberTextBox、 ValidationTextBox 和 TextBox 派生， 所有对这些类可用的方法也对它可用。另外，也可用下列约束方法：

  • setCurrency($currency): 设置要使用的货币类型； 遵循 » ISO-4217 规范。

  • getCurrency(): 获取当前货币类型。

  • setSymbol($symbol): 设置 3-letter » ISO-4217 货币符号。

  • getSymbol(): 获取当前货币符号。

  • setFractional($flag): 设置是否支持小数值。

  • getFractional(): 获取小数标记的状态。

Example #8 货币文字框 dijit 元素用法范例

$form->addElement(
    'CurrencyTextBox',
    'foo',
    array(
        'label'          => 'Currency:',
        'required'       => true,
        'currency'       => 'USD',
        'invalidMessage' => 'Invalid amount. Include dollar sign, commas, and cents.',
        'fractional'     => false,
    )
);

日期文字框

日期文字框提供一个下拉式日历用来选择日期，也有一个客户端的日期校验和格式化。

在内部，日期文字框从 ValidationTextBox 和 TextBox 派生， 所有对这些类可用的方法也对它可用。另外，下列方法也可以独立使用：

  • setAmPm($flag) 和 getAmPm(): 是否在时间上使用 AM/PM。

  • setStrict($flag) 和 getStrict(): 是否用严格的正则表达式校验输入。如果是缺省的 false，则对空白字符和一些缩写不严格检查。

  • setLocale($locale) 和 getLocale(): 设置和获取用于特定元素的地方。

  • setDatePattern($pattern) 和 getDatePattern(): 提供和读取 » unicode 日期格式模型 来格式化日期。

  • setFormatLength($formatLength) 和 getFormatLength(): 提供和读取格式长度类型，是 "long"、 "short"、 "medium" 或 "full" 其中之一。

  • setSelector($selector) 和 getSelector(): 提供和读取选择器的风格， "date" 或 "time"。

Example #9 日期文字框 dijit 元素用法范例

$form->addElement(
    'DateTextBox',
    'foo',
    array(
        'label'          => 'Date:',
        'required'       => true,
        'invalidMessage' => 'Invalid date specified.',
        'formatLength'   => 'long',
    )
);

水平滑尺（HorizontalSlider）

水平滑尺提供了一个滑尺 UI 小部件用来在一个范围内选择数值。 在内部，它设置一个隐藏元素的值然后由表单提交。

水平滑尺从 abstract Slider dijit element 派生。另外，有许多方法用来设置和配置滑尺刻度和刻度标签。

  • setTopDecorationDijit($dijit) 和 setBottomDecorationDijit($dijit): 设置 dijit 的名字用于滑尺的顶或底。这个不包括"dijit.form."前缀， 已经是最终的名字 － "HorizontalRule" 或 "HorizontalRuleLabels"。

  • setTopDecorationContainer($container) 和 setBottomDecorationContainer($container): 指定用于刻度的容器元素的名字，如：'topRule'、 'topContainer'等。

  • setTopDecorationLabels(array $labels) 和 setBottomDecorationLabels(array $labels): 设置标签用于 RuleLabels dijit 类型之一，这些是索引数组； 指定一个空间来跳过给定的标签位置（如开头或结尾）。

  • setTopDecorationParams(array $params) 和 setBottomDecorationParams(array $params): 配置给定的刻度或刻度标签 dijit 的 dijit 参数。

  • setTopDecorationAttribs(array $attribs) 和 setBottomDecorationAttribs(array $attribs): 指定给定的刻度或刻度标签 HTML 元素容器的 HTML 属性。

  • getTopDecoration() 和 getBottomDecoration(): 获取所有由上述增变器给定规则或 RuleLabels 定义的元数据。

Example #10 水平滑尺 dijit 元素用法范例

下面创建一个整数范围为 -10到10的水平滑尺。顶上有 20%、 40%、 60% 和 80%标记。 底下有 0 、50% 和 100%。每次改变，隐藏元素的值就更新一次。

$form->addElement(
    'HorizontalSlider',
    'horizontal',
    array(
        'label'                     => 'HorizontalSlider',
        'value'                     => 5,
        'minimum'                   => -10,
        'maximum'                   => 10,
        'discreteValues'            => 11,
        'intermediateChanges'       => true,
        'showButtons'               => true,
        'topDecorationDijit'        => 'HorizontalRuleLabels',
        'topDecorationContainer'    => 'topContainer',
        'topDecorationLabels'       => array(
                ' ',
                '20%',
                '40%',
                '60%',
                '80%',
                ' ',
        ),
        'topDecorationParams'      => array(
            'container' => array(
                'style' => 'height:1.2em; font-size=75%;color:gray;',
            ),
            'list' => array(
                'style' => 'height:1em; font-size=75%;color:gray;',
            ),
        ),
        'bottomDecorationDijit'     => 'HorizontalRule',
        'bottomDecorationContainer' => 'bottomContainer',
        'bottomDecorationLabels'    => array(
                '0%',
                '50%',
                '100%',
        ),
        'bottomDecorationParams'   => array(
            'list' => array(
                'style' => 'height:1em; font-size=75%;color:gray;',
            ),
        ),
    )
);

数字微调控制器（NumberSpinner）

数字微调控制器是一个文本元素用来输入数字值；它也包括用于增加和减少一定值的元素。

可用方法如下：

  • setDefaultTimeout($timeout) 和 getDefaultTimeout(): 设置和获取缺省超时值，以毫秒为单位， 当按住按钮时，数值就发生变化。

  • setTimeoutChangeRate($rate) 和 getTimeoutChangeRate(): 设置和获取比率，以毫秒为单位， 就是当按住按钮时，数值的变化率。

  • setLargeDelta($delta) 和 getLargeDelta(): 设置和读取当按钮被按住数字应当改变的值的大小。

  • setSmallDelta($delta) 和 getSmallDelta(): 设置和读取当按钮被按住一次数字的变化量。

  • setIntermediateChanges($flag) 和 getIntermediateChanges(): 设置和读取当按钮被按住时是否显示数值的标志。

  • setRangeMessage($message) 和 getRangeMessage(): 设置和读取指示可用数值范围的信息。

  • setMin($value) 和 getMin(): 设置和获取最小可能值。

  • setMax($value) 和 getMax(): 设置和获取最大可能值。

Example #11 数字微调控制器 dijit 元素用法范例

$form->addElement(
    'NumberSpinner',
    'foo',
    array(
        'value'             => '7',
        'label'             => 'NumberSpinner',
        'smallDelta'        => 5,
        'largeDelta'        => 25,
        'defaultTimeout'    => 500,
        'timeoutChangeRate' => 100,
        'min'               => 9,
        'max'               => 1550,
        'places'            => 0,
        'maxlength'         => 20,
    )
);

数字框

数字框是一个文本元素用来输入数字值，不象数字增变器，数字框用手工输入。 校验和限制可以使数值在一定的范围并符合一定的格式。

在内部，数字框从 ValidationTextBox 和 TextBox派生； 所有对这些类可用的方法都可用，另外，下列方法可以独立使用：

  • setLocale($locale) 和 getLocale(): 指定和获取一个特定或预备的地方来使用 dijit。

  • setPattern($pattern) 和 getPattern(): 设置和获取一个 » 数字模型格式 来格式化数字。

  • setType($type) 和 getType(): 设置和获取数字格式类型（应当为 'decimal'、'percent' 或 'currency'其中之一 ）。

  • setPlaces($places) 和 getPlaces():设置和获取有多少小数位。

  • setStrict($flag) 和 getStrict(): 设置和读取严格标志的值，它用来指示对空白字符和非数字字符控制的严格程度。

Example #12 数字框 dijit 元素用法范例

$form->addElement(
    'NumberTextBox',
    'elevation',
    array(
        'label'          => 'NumberTextBox',
        'required'       => true,
        'invalidMessage' => 'Invalid elevation.',
        'places'         => 0,
        'constraints'    => array(
            'min'    => -20000,
            'max'    => 20000,
        ),
    )
);

密码框

密码框是个 ValidationTextBox，它和密码输入有联系；它唯一的意图是允许 dijit-themed 文本输入密码并提供客户端校验。

在内部，密码框从 ValidationTextBox 和 TextBox 派生； 所有对这些类可用的方法都可用。

Example #13 密码框 dijit 元素用法范例

$form->addElement(
    'PasswordTextBox',
    'password',
    array(
        'label'          => 'Password',
        'required'       => true,
        'trim'           => true,
        'lowercase'      => true,
        'regExp'         => '^[a-z0-9]{6,}$',
        'invalidMessage' => 'Invalid password; must be at least 6 alphanumeric characters',
    )
);

单选按钮

单选按钮封装了标准单选输入元素来提供一个和其它 dojo dijits 一致的外观。 （因为英文为 radio button，单选按钮在过去也被翻译为无线电按钮，但从功能上讲，单选按钮更准确 Jason Qi注）

单选按钮从 DijitMulti 继承，它让你通过 setMultiOptions() 和 setMultiOption() 方法来指定选择选项。

缺省地，该元素注册一个 InArray 校验器，它依靠注册的选项的数组键来校验。 你可以通过调用 setRegisterInArrayValidator(false) 或传递一个 false 值给 registerInArrayValidator配置键来禁止该行为。

Example #14 单选按钮 dijit 元素用法范例

$form->addElement(
    'RadioButton',
    'foo',
    array(
        'label' => 'RadioButton',
        'multiOptions'  => array(
            'foo' => 'Foo',
            'bar' => 'Bar',
            'baz' => 'Baz',
        ),
        'value' => 'bar',
    )
);

滑尺摘要元素

水平滑尺 和 垂直滑尺 都是从滑尺摘要元素派生而来的。它包含了许多通用的方法来配置你的滑尺，包括：

  • setClickSelect($flag) 和 getClickSelect(): 设置和获取确定是否点击滑尺来可以修改数值的标志。

  • setIntermediateChanges($flag) 和 getIntermediateChanges(): 设置和获取是否对每个滑尺修改时间发送通知的标志。

  • setShowButtons($flag) 和 getShowButtons(): 设置和获取是否在两端显示按钮的标志。如果有的话，客户可以通过点击按钮来修改滑尺的值。

  • setDiscreteValues($value) 和 getDiscreteValues(): 设置和获取滑尺的不连续的数值。

  • setMaximum($value) 和 getMaximum():设置滑尺的最大值。

  • setMinimum($value) and getMinimum():设置滑尺的最小值。

  • setPageIncrement($value) 和 getPageIncrement(): 设置滑尺在键盘事件上修改的数量。

范例在每个具体的继承类里提供。

提交按钮

虽然没有叫提交按钮的 Dijit，但我们还是在此提供一个按钮 dijit 用来提交 表单而不需请求任何另外的 javascript 绑定。它的工作方式和 按钮 dijit 一模一样。

Example #15 Example SubmitButton dijit element usage

$form->addElement(
    'SubmitButton',
    'foo',
    array(
        'required'   => false,
        'ignore'     => true,
        'label'      => 'Submit Button!',
    )
);

文字框

文字框用来输入文字，在外观上和其它 dijit 保持一致。然而，它有一些过滤和校验的功能，详见下列方法：

  • setLowercase($flag) 和 getLowercase(): 设置和获取是否把输入转为小写的标志。

  • setPropercase($flag) 和 getPropercase(): 设置和获取是否把输入转换为适当的大小写的标志。 Case.

  • setUppercase($flag) 和 getUppercase(): 设置和获取是否把输入转为大写的标志。

  • setTrim($flag) 和 getTrim(): 设置和获取是否把引导和拖尾的空白字符去掉的标志。

  • setMaxLength($length) 和 getMaxLength(): 设置和获取输入的最大长度。

Example #16 文字框 dijit 元素用法范例

$form->addElement(
    'TextBox',
    'foo',
    array(
        'value'      => 'some text',
        'label'      => 'TextBox',
        'trim'       => true,
        'propercase' => true,
    )
);

Textarea

Textarea 就像标准的 HTML textarea一样。然而，它不支持行列的设置。 作为替代，textarea 宽度可以用标准的 CSS 来设置，行就完全忽略了。当输入字符增加时，textarea 就垂直增长。

Example #17 Textarea dijit 元素用法范例

$form->addElement(
    'Textarea',
    'textarea',
    array(
        'label'    => 'Textarea',
        'required' => true,
        'style'    => 'width: 200px;',
    )
);

时间文字框

时间文字框是提供下拉式选择时间的文字输入框。下拉框可配置为显示一特定的时间窗口，带有特定的增量。

在内部，时间文字框从 日期文字框、 校验文字框 和 文字框 派生。 所有对这些类可用的方法都可用。另外，下列方法可以独立使用：

  • setTimePattern($pattern) 和 getTimePattern(): 设置和获取 » unicode 时间格式模型 来格式化时间。

  • setClickableIncrement($format) 和 getClickableIncrement(): 设置 » ISO-8601 字符串，来表示 每个在时间 picker increses 的可点击的元素的数量。

  • setVisibleIncrement($format) 和 getVisibleIncrement(): 在时间选择器中设置增量的可见性，必须遵循 ISO-8601格式。

  • setVisibleRange($format) 和 getVisibleRange(): 在时间选择器中在给定的时刻，设置和获取可见时间的范围，必须遵循 ISO-8601格式。

Example #18 时间文字框 dijit 元素用法范例

下面讲生成一个时间文字框，每次显示 2 小时，增量是 10 分钟。

$form->addElement(
    'TimeTextBox',
    'foo',
    array(
        'label'              => 'TimeTextBox',
        'required'           => true,
        'visibleRange'       => 'T04:00:00',
        'visibleIncrement'   => 'T00:10:00',
        'clickableIncrement' => 'T00:10:00',
    )
);

校验文字框

校验文字框添加校验和限制给文字输入。 在内部，它从 文字框 派生， 并增加了下列访问器和增变器来处理 dijit 参数：

  • setInvalidMessage($message) 和 getInvalidMessage(): 设置和获取工具提示消息来显示什么时候值没有通过校验。

  • setPromptMessage($message) 和 getPromptMessage(): 设置和获取工具提示消息来显示元素用法。

  • setRegExp($regexp) 和 getRegExp(): 设置和获取用于校验元素的正则表达式。正则表达式不需要边界（不象 PHP 的 preg* 函数家族）。

  • setConstraint($key, $value) 和 getConstraint($key): 设置和获取另外的限制，用于校验元素；使用子类。限制存储在 dijit 参数数组中，键值为 'constraints'。

  • setConstraints(array $constraints) 和 getConstraints(): 设置和获取独立的限制，用于校验元素，是哟功能子类。

  • hasConstraint($key): 测试是否有给定的限制存在。

  • removeConstraint($key) 和 clearConstraints(): 删除元素中一个或所有的限制。

Example #19 校验文字框 dijit 元素用法范例

下面生成一个校验文字框，要求只包含字符的单个字符串（例如，没有空格，大部分标点符号无效）。

$form->addElement(
    'ValidationTextBox',
    'foo',
    array(
        'label'          => 'ValidationTextBox',
        'required'       => true,
        'regExp'         => '[\w]+',
        'invalidMessage' => 'Invalid non-space text.',
    )
);

垂直滑尺（VerticalSlider）

垂直滑尺是水平滑尺的兄弟， 操作基本相同。唯一的区别是，对垂直滑尺来说使用了 'left*' 和 'right*' 替换了 在水平滑尺中的 'top*' 和 'bottom*'，并且使用 VerticalRule 和 VerticalRuleLabels 分别替代了 HorizontalRule 和 HorizontalRuleLabels。

Example #20 垂直 dijit 元素使用范例

下面创建一个整数范围为 -10到10的垂直滑尺。左边有 20%、 40%、 60% 和 80%标记。 右边有 0 、50% 和 100%。每次改变，隐藏元素的值就更新一次。

$form->addElement(
    'VerticalSlider',
    'foo',
    array(
        'label'                    => 'VerticalSlider',
        'value'                    => 5,
        'style'                    => 'height: 200px; width: 3em;',
        'minimum'                  => -10,
        'maximum'                  => 10,
        'discreteValues'           => 11,
        'intermediateChanges'      => true,
        'showButtons'              => true,
        'leftDecorationDijit'      => 'VerticalRuleLabels',
        'leftDecorationContainer'  => 'leftContainer',
        'leftDecorationLabels'     => array(
                ' ',
                '20%',
                '40%',
                '60%',
                '80%',
                ' ',
        ),
        'rightDecorationDijit' => 'VerticalRule',
        'rightDecorationContainer' => 'rightContainer',
        'rightDecorationLabels' => array(
                '0%',
                '50%',
                '100%',
        ),
    )
);

Dojo 表单范例

Example #21 使用 Zend_Dojo_Form

和 Zend_Form 一起使用 Dojo的最容易的办法是利用 Zend_Dojo_Form， 直接使用或继承都可以。这个范例继承 Zend_Dojo_Form，并示范了所有 dijit 元素的用法。 它生成了四个子表单，并装饰了表单来使用 TabContainer，把每个子表单显示在它自己的 tab 上。

class My_Form_Test extends Zend_Dojo_Form
{
    /**
     * Options to use with select elements
     */
    protected $_selectOptions = array(
        'red'    => 'Rouge',
        'blue'   => 'Bleu',
        'white'  => 'Blanc',
        'orange' => 'Orange',
        'black'  => 'Noir',
        'green'  => 'Vert',
    );

    /**
     * Form initialization
     *
     * @return void
     */
    public function init()
    {
        $this->setMethod('post');
        $this->setAttribs(array(
            'name'  => 'masterForm',
        ));
        $this->setDecorators(array(
            'FormElements',
            array('TabContainer', array(
                'id' => 'tabContainer',
                'style' => 'width: 600px; height: 500px;',
                'dijitParams' => array(
                    'tabPosition' => 'top'
                ),
            )),
            'DijitForm',
        ));
        $textForm = new Zend_Dojo_Form_SubForm();
        $textForm->setAttribs(array(
            'name'   => 'textboxtab',
            'legend' => 'Text Elements',
            'dijitParams' => array(
                'title' => 'Text Elements',
            ),
        ));
        $textForm->addElement(
                'TextBox',
                'textbox',
                array(
                    'value'      => 'some text',
                    'label'      => 'TextBox',
                    'trim'       => true,
                    'propercase' => true,
                )
            )
            ->addElement(
                'DateTextBox',
                'datebox',
                array(
                    'value' => '2008-07-05',
                    'label' => 'DateTextBox',
                    'required'  => true,
                )
            )
            ->addElement(
                'TimeTextBox',
                'timebox',
                array(
                    'label' => 'TimeTextBox',
                    'required'  => true,
                )
            )
            ->addElement(
                'CurrencyTextBox',
                'currencybox',
                array(
                    'label' => 'CurrencyTextBox',
                    'required'  => true,
                    // 'currency' => 'USD',
                    'invalidMessage' => 'Invalid amount. Include dollar sign, commas, and cents.',
                    // 'fractional' => true,
                    // 'symbol' => 'USD',
                    // 'type' => 'currency',
                )
            )
            ->addElement(
                'NumberTextBox',
                'numberbox',
                array(
                    'label' => 'NumberTextBox',
                    'required'  => true,
                    'invalidMessage' => 'Invalid elevation.',
                    'constraints' => array(
                        'min' => -20000,
                        'max' => 20000,
                        'places' => 0,
                    )
                )
            )
            ->addElement(
                'ValidationTextBox',
                'validationbox',
                array(
                    'label' => 'ValidationTextBox',
                    'required'  => true,
                    'regExp' => '[\w]+',
                    'invalidMessage' => 'Invalid non-space text.',
                )
            )
            ->addElement(
                'Textarea',
                'textarea',
                array(
                    'label'    => 'Textarea',
                    'required' => true,
                    'style'    => 'width: 200px;',
                )
            );
        $toggleForm = new Zend_Dojo_Form_SubForm();
        $toggleForm->setAttribs(array(
            'name'   => 'toggletab',
            'legend' => 'Toggle Elements',
        ));
        $toggleForm->addElement(
                'NumberSpinner',
                'ns',
                array(
                    'value'             => '7',
                    'label'             => 'NumberSpinner',
                    'smallDelta'        => 5,
                    'largeDelta'        => 25,
                    'defaultTimeout'    => 1000,
                    'timeoutChangeRate' => 100,
                    'min'               => 9,
                    'max'               => 1550,
                    'places'            => 0,
                    'maxlength'         => 20,
                )
            )
            ->addElement(
                'Button',
                'dijitButton',
                array(
                    'label' => 'Button',
                )
            )
            ->addElement(
                'CheckBox',
                'checkbox',
                array(
                    'label' => 'CheckBox',
                    'checkedValue'  => 'foo',
                    'uncheckedValue'  => 'bar',
                    'checked' => true,
                )
            )
            ->addElement(
                'RadioButton',
                'radiobutton',
                array(
                    'label' => 'RadioButton',
                    'multiOptions'  => array(
                        'foo' => 'Foo',
                        'bar' => 'Bar',
                        'baz' => 'Baz',
                    ),
                    'value' => 'bar',
                )
            );
        $selectForm = new Zend_Dojo_Form_SubForm();
        $selectForm->setAttribs(array(
            'name'   => 'selecttab',
            'legend' => 'Select Elements',
        ));
        $selectForm->addElement(
                'ComboBox',
                'comboboxselect',
                array(
                    'label' => 'ComboBox (select)',
                    'value' => 'blue',
                    'autocomplete' => false,
                    'multiOptions' => $this->_selectOptions,
                )
            )
            ->addElement(
                'ComboBox',
                'comboboxremote',
                array(
                    'label' => 'ComboBox (remoter)',
                    'storeId' => 'stateStore',
                    'storeType' => 'dojo.data.ItemFileReadStore',
                    'storeParams' => array(
                        'url' => '/js/states.txt',
                    ),
                    'dijitParams' => array(
                        'searchAttr' => 'name',
                    ),
                )
            )
            ->addElement(
                'FilteringSelect',
                'filterselect',
                array(
                    'label' => 'FilteringSelect (select)',
                    'value' => 'blue',
                    'autocomplete' => false,
                    'multiOptions' => $this->_selectOptions,
                )
            )
            ->addElement(
                'FilteringSelect',
                'filterselectremote',
                array(
                    'label' => 'FilteringSelect (remoter)',
                    'storeId' => 'stateStore',
                    'storeType' => 'dojo.data.ItemFileReadStore',
                    'storeParams' => array(
                        'url' => '/js/states.txt',
                    ),
                    'dijitParams' => array(
                        'searchAttr' => 'name',
                    ),
                )
            );
        $sliderForm = new Zend_Dojo_Form_SubForm();
        $sliderForm->setAttribs(array(
            'name'   => 'slidertab',
            'legend' => 'Slider Elements',
        ));
        $sliderForm->addElement(
                'HorizontalSlider',
                'horizontal',
                array(
                    'label' => 'HorizontalSlider',
                    'value' => 5,
                    'minimum' => -10,
                    'maximum' => 10,
                    'discreteValues' => 11,
                    'intermediateChanges' => true,
                    'showButtons' => true,
                    'topDecorationDijit' => 'HorizontalRuleLabels',
                    'topDecorationContainer' => 'topContainer',
                    'topDecorationLabels' => array(
                            ' ',
                            '20%',
                            '40%',
                            '60%',
                            '80%',
                            ' ',
                    ),
                    'topDecorationParams' => array(
                        'container' => array(
                            'style' => 'height:1.2em; font-size=75%;color:gray;',
                        ),
                        'list' => array(
                            'style' => 'height:1em; font-size=75%;color:gray;',
                        ),
                    ),
                    'bottomDecorationDijit' => 'HorizontalRule',
                    'bottomDecorationContainer' => 'bottomContainer',
                    'bottomDecorationLabels' => array(
                            '0%',
                            '50%',
                            '100%',
                    ),
                    'bottomDecorationParams' => array(
                        'list' => array(
                            'style' => 'height:1em; font-size=75%;color:gray;',
                        ),
                    ),
                )
            )
            ->addElement(
                'VerticalSlider',
                'vertical',
                array(
                    'label' => 'VerticalSlider',
                    'value' => 5,
                    'style' => 'height: 200px; width: 3em;',
                    'minimum' => -10,
                    'maximum' => 10,
                    'discreteValues' => 11,
                    'intermediateChanges' => true,
                    'showButtons' => true,
                    'leftDecorationDijit' => 'VerticalRuleLabels',
                    'leftDecorationContainer' => 'leftContainer',
                    'leftDecorationLabels' => array(
                            ' ',
                            '20%',
                            '40%',
                            '60%',
                            '80%',
                            ' ',
                    ),
                    'rightDecorationDijit' => 'VerticalRule',
                    'rightDecorationContainer' => 'rightContainer',
                    'rightDecorationLabels' => array(
                            '0%',
                            '50%',
                            '100%',
                    ),
                )
            );

        $this->addSubForm($textForm, 'textboxtab')
             ->addSubForm($toggleForm, 'toggletab')
             ->addSubForm($selectForm, 'selecttab')
             ->addSubForm($sliderForm, 'slidertab');
    }
}

Example #22 修改已存在的表单来使用 Dojo

通过使用 Zend_Dojo::enableForm() 静态方法，已存在的表单也可以使用 Dojo。

第一个范例示范装饰已存在的表单实例：

$form = new My_Custom_Form();
Zend_Dojo::enableForm($form);
$form->addElement(
'ComboBox',
'query',
array(
    'label'        => 'Color:',
    'value'        => 'blue',
    'autocomplete' => false,
    'multiOptions' => array(
        'red'    => 'Rouge',
        'blue'   => 'Bleu',
        'white'  => 'Blanc',
        'orange' => 'Orange',
        'black'  => 'Noir',
        'green'  => 'Vert',
    ),
)
);

另外，你可以在表单初始化上做点小文章：

class My_Custom_Form extends Zend_Form
{
    public function init()
    {
        Zend_Dojo::enableForm($this);

        // ...
    }
}

当然，如果你可以那样做 ... 你可以并应该简单地修改类来继承 Zend_Dojo_Form， 它可以随时替换已经 Dojo-enabled 的 Zend_Form ...

Dojo 视图助手
Zend_Dojo
Zend Framework手册 中文版
Zend_Dojo build layer support
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Dojo
  • 简介
  • Zend_Dojo_Data: dojo.data Envelopes
  • Dojo 视图助手
  • Dojo 表单元素和装饰器
  • Zend_Dojo build layer support


Zend_Dojo build layer support - Zend Framework Manual

Dojo 表单元素和装饰器
Zend_Dojo
Zend Framework手册 中文版
Zend_Dom

Zend_Dojo build layer support

Introduction

Dojo build layers provide a clean path from development to production when using Dojo for your UI layer. In development, you can have load-on-demand, rapid application prototyping; a build layer takes all Dojo dependencies and compiles them to a single file, optionally stripping whitespace and comments, and performing code heuristics to allow further minification of variable names. Additionally, it can do CSS minification.

In order to create a build layer, you would traditionally create a JavaScript file that has dojo.require statements for each dependency, and optionally some additional code that might run when the script is loaded. As an example:

  1. dojo.provide("custom.main");
  2.
  3. dojo.require("dijit.layout.TabContainer");
  4. dojo.require("dijit.layout.ContentPane");
  5. dojo.require("dijit.form.Form");
  6. dojo.require("dijit.form.Button");
  7. dojo.require("dijit.form.TextBox");

This script is generally referred to as a "layer" script.

Then, in your application's layout, you'd instruct Dojo to load this module:

  1. <html>
  2. <head>
  3.     <script type="text/javascript" src="/js/dojo/dojo.js"></script>
  4.     <script type="text/javascript">
  5.         dojo.registerModulePath("custom", "../custom/");
  6.         dojo.require("custom.main");
  7.     </script>

If you use Zend_Dojo to do this, you'd do the following:

  1. $view->dojo()->registerModulePath('custom', '../custom/')
  2.              ->requireModule('custom.main');

But since Zend_Dojo aggregates your various dojo.require statements, how do you create your layer script? You could open each page and view the generated dojo.require statements, and cut and paste them into a layer script file manually.

However, a better solution exists: since Zend_Dojo aggregates this information already, you can simply pull that information and build your layer file. This is the purpose of Zend_Dojo_BuildLayer.

Generating Custom Module Layers with Zend_Dojo_BuildLayer

At its simplest, you simply instantiate Zend_Dojo_BuildLayer, feed it the view object and the name of your custom module layer, and have it generate the content of the layer file; it is up to you to then write it to disk.

As an example, let's say you wanted to create the module layer "custom.main". Assuming you follow the recommended project directory structure, and that you are storing your JavaScript files under public/js/, you could do the following:

  1. $build = new Zend_Dojo_BuildLayer(array(
  2.     'view'      => $view,
  3.     'layerName' => 'custom.main',
  4. ));
  5.
  6. $layerContents = $build->generateLayerScript();
  7. $filename      = APPLICATION_PATH . '/../public/js/custom/main.js';
  8. if (!dir_exists(dirname($filename))) {
  9.     mkdir(dirname($filename));
  10. }
  11. file_put_contents($filename, $layerContents);

When should you do the above? For it to work correctly, you need to do it after all view scripts and the layout have been rendered, to ensure that the dojo() helper is fully populated. One easy way to do so is using a front controller plugin, with a dispatchLoopShutdown() hook:

  1. class App_Plugin_DojoLayer extends Zend_Controller_Plugin_Abstract
  2. {
  3.     public $layerScript = APPLICATION_PATH . '/../public/js/custom/main.js';
  4.     protected $_build;
  5.
  6.     public function dispatchLoopShutdown()
  7.     {
  8.         if (!file_exists($this->layerScript)) {
  9.             $this->generateDojoLayer();
  10.         }
  11.     }
  12.
  13.     public function getBuild()
  14.     {
  15.         $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper(
  16.             'ViewRenderer'
  17.         );
  18.         $viewRenderer->initView();
  19.         if (null === $this->_build) {
  20.             $this->_build = new Zend_Dojo_BuildLayer(array(
  21.                 'view'      => $viewRenderer->view,
  22.                 'layerName' => 'custom.main',
  23.             ));
  24.         }
  25.         return $this->_build;
  26.     }
  27.
  28.     public function generateDojoLayer()
  29.     {
  30.         $build = $this->getBuild();
  31.         $layerContents = $build->generateLayerScript();
  32.         if (!dir_exists(dirname($this->layerScript))) {
  33.             mkdir(dirname($this->layerScript));
  34.         }
  35.         file_put_contents($this->layerScript, $layerContents);
  36.     }
  37. }

Note: Do not generate the layer on every page
 It's tempting to generate the layer script on each and every page. However, this is resource intensive, as it must write to the disk on each page. Additionally, since the mtime of the file will keep changing, you will get no benefits of client-side caching. Write the file once.

BuildLayer options

The above functionality will suffice for most situations. For those needing more customization, a variety of options may be invoked.

Setting the view object

While the view object may be passed during instantiation, you may also pass it in to an instance via the setView() method:

  1. $build->setView($view);

Setting the layer name

While the layer name may be passed during instantiation, you may also pass it in to an instance via the setLayerName() method:

  1. $build->setLayerName("custom.main");

Including onLoad events in the generated layer

dojo.addOnLoad is a useful utility for specifying actions that should trigger when the DOM has finished loading. The dojo() view helper can create these statements via its addOnLoad() and onLoadCapture() methods. In some cases, it makes sense to push these into your layer file instead of rendering them via your view scripts.

By default, these are not rendered; to enable them, pass the consumeOnLoad configuration key during instantiation:

  1. $build = new Zend_Dojo_BuildLayer(array(
  2.     'view'          => $view,
  3.     'layerName'     => 'custom.main',
  4.     'consumeOnLoad' => true,
  5. ));

Alternately, you can use the setConsumeOnLoad() method after instantiation:

  1. $build->setConsumeOnLoad(true);

Including captured JavaScript in the generated layer

The dojo() view helper includes methods for capturing arbitrary JavaScript to include in the <script> tag containing the various dojo.require and dojo.addOnLoad statements. This can be useful when creating default data stores or globally scoped objects used throughout your application.

By default, these are not rendered; to enable them, pass the consumeJavascript configuration key during instantiation:

  1. $build = new Zend_Dojo_BuildLayer(array(
  2.     'view'              => $view,
  3.     'layerName'         => 'custom.main',
  4.     'consumeJavascript' => true,
  5. ));

Alternately, you can use the setConsumeJavascript() method after instantiation:

  1. $build->setConsumeJavascript(true);

Generating Build Profiles with Zend_Dojo_BuildLayer

One of the chief benefits of a Dojo module layer is that it facilitates the creation of a custom build. Zend_Dojo_BuildLayer has functionality for generate build profiles.

The simplest use case is to utilize the generateBuildProfile() method and send the output to a file:

  1. $build = new Zend_Dojo_BuildLayer(array(
  2.     'view'      => $view,
  3.     'layerName' => 'custom.main',
  4. ));
  5.
  6. $profile   = $build->generateBuildProfile();
  7. $filename  = APPLICATION_PATH . '/../misc/scripts/custom.profile.js';
  8. file_put_contents($filename, $profile);

Just like generating layers, you may want to automate this via a dispatchLoopShutdown() plugin hook; you could even simply modify the one shown for generating layers to read as follows:

  1. class App_Plugin_DojoLayer extends Zend_Controller_Plugin_Abstract
  2. {
  3.     public $layerScript  = APPLICATION_PATH
  4.                          . '/../public/js/custom/main.js';
  5.     public $buildProfile = APPLICATION_PATH
  6.                          . '/../misc/scripts/custom.profile.js';
  7.     protected $_build;
  8.
  9.     public function dispatchLoopShutdown()
  10.     {
  11.         if (!file_exists($this->layerScript)) {
  12.             $this->generateDojoLayer();
  13.         }
  14.         if (!file_exists($this->buildProfile)) {
  15.             $this->generateBuildProfile();
  16.         }
  17.     }
  18.
  19.     public function generateDojoLayer() { /* ... */ }
  20.
  21.     public function generateBuildProfile()
  22.     {
  23.         $profile = $this->getBuild()->generateBuildProfile();
  24.         file_put_contents($this->buildProfile, $profile);
  25.     }
  26.
  27. }

As noted, with module layers, you should only create the file once.

Build Profile options

The above functionality will suffice for most situations. The only way to customize build profile generation is to provide additional build profile options to utilize.

As an example, you may want to specify what type of optimizations should be performed, whether or not to optimize CSS files in the layer, whether or not to copy tests into the build, etc. For a listing of available options, you should read the » Dojo Build documentation and » accompanying documentation.

Setting these options is trivial: use the addProfileOption(), addProfileOptions(), or setProfileOptions() methods. The first method adds a single key and value option pair, the second will add several, and the third will overwrite any options with the list of key and value pairs provided.

By default, the following options are set:

  1. {
  2.     action:        "release",
  3.     optimize:      "shrinksafe",
  4.     layerOptimize: "shrinksafe",
  5.     copyTests:     false,
  6.     loader:        "default",
  7.     cssOptimize:   "comments"
  8. }

You can pass in whatever key and value pairs you want; the Dojo build script will ignore those it does not understand.

As an example of setting options:

  1. // A single option:
  2. $build->addProfileOption('version', 'zend-1.3.1');
  3.
  4. // Several options:
  5. $build->addProfileOptions(array(
  6.     'loader'   => 'xdomain',
  7.     'optimize' => 'packer',
  8. ));
  9.
  10. // Or overwrite options:
  11. $build->setProfileOptions(array(
  12.     'version'  => 'custom-1.3.1',
  13.     'loader'   => 'shrinksafe',
  14.     'optimize' => 'shrinksafe',
  15. ));
Dojo 表单元素和装饰器
Zend_Dojo
Zend Framework手册 中文版
Zend_Dom
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Dojo
  • 简介
  • Zend_Dojo_Data: dojo.data Envelopes
  • Dojo 视图助手
  • Dojo 表单元素和装饰器
  • Zend_Dojo build layer support


Zend_Dom - Zend Framework Manual

Zend_Dojo build layer support
Zend Framework Reference
Zend Framework手册 中文版
简介

Zend_Dom

Table of Contents
  • 简介
  • Zend_Dom_Query
Zend_Dojo build layer support
Zend Framework Reference
Zend Framework手册 中文版
简介
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


简介 - Zend Framework Manual

Zend_Dom
Zend_Dom
Zend Framework手册 中文版
Zend_Dom_Query

简介

Zend_Dom 提供了对 DOM 文档和结构进行操作的工具。 现在，Zend_Dom_Query 提供了利用 XPath 或 CSS 选择器的统一接口的 DOM 文档查询功能。

Zend_Dom
Zend_Dom
Zend Framework手册 中文版
Zend_Dom_Query
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Dom
  • 简介
  • Zend_Dom_Query


Zend_Dom_Query - Zend Framework Manual

简介
Zend_Dom
Zend Framework手册 中文版
Zend_Exception

Zend_Dom_Query

Zend_Dom_Query 为利用 XPath 或 CSS 选择器来查询 XML 和 (X)HTML 文档提供了机制。 它为帮助 MVC 应用的功能测试而开发，但也用于 screen scrapers 的快速开发。

当用 XML 结构查询文档时，对于 web 开发者来说，CSS 选择器符号简单而熟悉。 对开发过 Cascading Style Sheets 或用过提供使用 CSS 选择器 （» Prototype's $$() 和 » Dojo's dojo.query 都是组件的灵魂）选择节点的功能的 Javascript 工具箱的开发者来说，符号应当很熟悉。

操作理论

要使用 Zend_Dom_Query，你需要初始化一个 Zend_Dom_Query 对象，并可选地传递一个文档到查询（一字符串）。 一旦你有一个文档，可以使用 query() 或 queryXpath() 方法； 每个方法将返回带有任何匹配节点的 Zend_Dom_Query_Result 对象。

Zend_Dom_Query 和使用 DOMDocument + DOMXPath 的主要不同之处是可以依靠 CSS 选择器来选择。 你可以使用下列的任何组合：

  • element types: 提供一个元素类型来匹配： 'div'、 'a'、 'span'、 'h2' 等。

  • style attributes: 匹配 '.error'、 'div.error'、 'label.required' 等的 CSS 风格属性。 如果任何元素定义了超过一个风格，只要命名的风格出现在风格声明的任何地方，它将匹配。

  • id attributes: 匹配 '#content'、 'div#nav' 等的元素 ID 属性。

  • arbitrary attributes: 用于匹配的属性元素的属性。 有三个不同的匹配类型：

    • exact match: 属性和字符串精确地匹配： 'div[bar="baz"]' 表示带有 "bar" 属性的 div 元素精确地匹配值 "baz"。

    • word match: 包含匹配字符串 'div[bar~="baz"]' 的字符的 属性将匹配一个带有包含 "baz"字符的 "bar"属性的 div 元素。 '<div bar="foo baz">' 匹配，而'<div bar="foo bazbat">'不匹配。

    • substring match: 包含 'div[bar*="baz"]' 字符串的属性将匹配一个带有在它内部 任何地方包含字符串 "baz" 的 "bar" 属性的 div 元素。

  • direct descendents: 利用在选择器之间的 '>'表示直接的子孙。'div > span'将只选择 'div'直接的子孙 'span' 元素。 它可用于任何上述的选择器。

  • descendents: 把多个选择器集中成一字符串来表示一个搜索的层次。 'div .foo span #one' 选择一个 id 'one' 的元素，它是在 'span' 元素下任意深度的子孙， 它也是 'foo' 类下面任意深度的子孙，而 'foo' 元素是 'div' 元素下任意深度的子孙。 例如，在下面列表中，它将匹配带有 'One' 字符的链接：

    <div>
    <table>
        <tr>
            <td class="foo">
                <div>
                    Lorem ipsum <span class="bar">
                        <a href="/foo/bar" id="one">One</a>
                        <a href="/foo/baz" id="two">Two</a>
                        <a href="/foo/bat" id="three">Three</a>
                        <a href="/foo/bla" id="four">Four</a>
                    </span>
                </div>
            </td>
        </tr>
    </table>
</div>

一旦你执行了查询，你可以使用结果对象来确定节点的信息，同时，你也可以 把它们和/或它们的内容拿出来检查和处理。 Zend_Dom_Query_Result 实现 Countable 和 Iterator 并在内部存储结果为 DOMNodes/DOMElements。 作为例子，考虑下列的调用，它依靠上述的 HTML 来选择：

$dom = new Zend_Dom_Query($html);
$results = $dom->query('.foo .bar a');

$count = count($results); // get number of matches: 4
foreach ($results as $result) {
    // $result is a DOMElement
}

Zend_Dom_Query 也允许利用 queryXpath() method 直接 XPath 查询； 你可以传递任何有效的 XPath 查询给这个方法，它将返回一个 Zend_Dom_Query_Result 对象。

可用方法

Zend_Dom_Query 类家族有下列方法可用。

Zend_Dom_Query

下列方法对 Zend_Dom_Query 可用:

  • setDocumentXml($document): 指定一个查询使用的 XML 字符串。

  • setDocumentXhtml($document): 指定一个查询使用的 XHTML 字符串。

  • setDocumentHtml($document): 指定一个查询使用的 HTML 字符串。

  • setDocument($document): 指定一个查询使用的字符串； Zend_Dom_Query 将尝试自动检查文档类型。

  • getDocument(): 获取提供给对象的原始文档字符串。

  • getDocumentType(): 获取提供给对象的文档的类型；是 DOC_XML、 DOC_XHTML 或 DOC_HTML 类常量其中之一。

  • query($query): 使用 CSS 选择器符号查询文档。

  • queryXpath($xPathQuery): 使用 XPath 符号查询文档。

Zend_Dom_Query_Result

如前所述，Zend_Dom_Query_Result 实现 Iterator 和 Countable， 可用于 foreach 循环和 count() 函数。 另外，它有下列方法：

  • getCssQuery(): 返回用于处理结果（如果有的话）的 CSS 选择器查询。

  • getXpathQuery(): 返回用于处理结果的 XPath 查询。 在内部，Zend_Dom_Query 转换 CSS 选择器查选为 XPath，所以这个值将永远被组装。

  • getDocument(): 获取选择使用的文档。

简介
Zend_Dom
Zend Framework手册 中文版
Zend_Exception
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Dom
  • 简介
  • Zend_Dom_Query


Zend_Exception - Zend Framework Manual

Zend_Dom_Query
Zend Framework Reference
Zend Framework手册 中文版
使用“异常”

Zend_Exception

Table of Contents
  • 使用“异常”
  • Basic usage
  • Previous Exceptions
Zend_Dom_Query
Zend Framework Reference
Zend Framework手册 中文版
使用“异常”
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


使用“异常” - Zend Framework Manual

Zend_Exception
Zend_Exception
Zend Framework手册 中文版
Basic usage

使用“异常”

Zend Framework 抛出的所有异常都必须是 Zend_Exception 的子类的对象。

Example #1 捕捉一个异常的例子

<?php

try {
    Zend_Loader::loadClass('nonexistantclass');
} catch (Zend_Exception $e) {
    echo "Caught exception: " . get_class($e) . "\n";
    echo "Message: " . $e->getMessage() . "\n";
    // 处理错误的代码
}

请仔细查看ZF手册，了解具体的每种异常是由哪些方法抛出的，其抛出条件，还有具体是 Zend_Exception 的哪个子类的实例。

Zend_Exception
Zend_Exception
Zend Framework手册 中文版
Basic usage
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Exception
  • 使用“异常”
  • Basic usage
  • Previous Exceptions


Basic usage - Zend Framework Manual

使用“异常”
Zend_Exception
Zend Framework手册 中文版
Previous Exceptions

Basic usage

Zend_Exception is the base class for all exceptions thrown by Zend Framework. This class extends the base Exception class of PHP.

Example #1 Catch all Zend Framework exceptions

  1. try {
  2.     // your code
  3. } catch (Zend_Exception $e) {
  4.     // do something
  5. }

Example #2 Catch exceptions thrown by a specific component of Zend Framework

  1. try {
  2.     // your code
  3. } catch (Zend_Db_Exception $e) {
  4.     // do something
  5. }
使用“异常”
Zend_Exception
Zend Framework手册 中文版
Previous Exceptions
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Exception
  • 使用“异常”
  • Basic usage
  • Previous Exceptions


Previous Exceptions - Zend Framework Manual

Basic usage
Zend_Exception
Zend Framework手册 中文版
Zend_Feed

Previous Exceptions

Since Zend Framework 1.10, Zend_Exception implements the PHP 5.3 support for previous exceptions. Simply put, when in a catch block, you can throw a new exception that references the original exception, which helps provide additional context when debugging. By providing this support in Zend Framework, your code may now be forwards compatible with PHP 5.3.

Previous exceptions are indicated as the third argument to an exception constructor.

Example #1 Previous exceptions

  1. try {
  2.     $db->query($sql);
  3. } catch (Zend_Db_Statement_Exception $e) {
  4.     if ($e->getPrevious()) {
  5.         echo '[' . get_class($e)
  6.             . '] has the previous exception of ['
  7.             . get_class($e->getPrevious())
  8.             . ']' . PHP_EOL;
  9.     } else {
  10.         echo '[' . get_class($e)
  11.             . '] does not have a previous exception'
  12.             . PHP_EOL;
  13.     }
  14.
  15.     echo $e;
  16.     // displays all exceptions starting by the first thrown
  17.     // exception if available.
  18. }
Basic usage
Zend_Exception
Zend Framework手册 中文版
Zend_Feed
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Exception
  • 使用“异常”
  • Basic usage
  • Previous Exceptions


Zend_Feed - Zend Framework Manual

Previous Exceptions
Zend Framework Reference
Zend Framework手册 中文版
介绍

Zend_Feed

Table of Contents
  • 介绍
  • 导入Feeds
  • 从网页上获得Feed
  • RSS Feed的使用
  • Atom Feed的使用
  • 单个Atom条目的处理
  • 修改Feed和条目结构
  • 自定义Feed和条目类
  • Zend_Feed_Reader
  • Zend_Feed_Writer
  • Zend_Feed_Pubsubhubbub
Previous Exceptions
Zend Framework Reference
Zend Framework手册 中文版
介绍
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


介绍 - Zend Framework Manual

Zend_Feed
Zend_Feed
Zend Framework手册 中文版
导入Feeds

介绍

Zend_Feed提供了处理的 RSS 和 Atom Feed的功能。它提供了一套自然的方法用于 访问Feed元素、属性、和条目属性。 除此之外Zend_Feed还扩展提供了同样简单的方法 用于修改feed和条目的结构，并将结果转化成XML格式。不久的将来这些扩展可能会被 Atom Publishig Protocol(AtomPP)所支持。

Zend_Feed由一个Zend_Feed基类、一个Zend_Feed_Abstract抽象类以及一个用于表示Feed和条目的Zend_Feed_Entry_Abstract基类组成。这些类封装了 RSS 和 Atom 的feed和条目特性的，提供了一套自然的方法使他们用起来变得异常简单。

在下面的例子中，我们示范了一个获得一个RSS feed并将其中的一般部分相关数据保存到一个PHP数组中的简单实例，这样这些数据就能方便的用于输出、保存到数据库等等。

Note: Be aware
 许多RSS中的channel和item属性是不同的。RSS的规范中提供了许多可选的属性，因此在编写RSS相关应用代码时要充分考虑这点。

Example #1 用Zend_Feed来处理RSS Feed数据

<?php
require_once 'Zend/Feed.php';

// 取得最新的 Slashdot 头条新闻
try {
    $slashdotRss = Zend_Feed::import('http://rss.slashdot.org/Slashdot/slashdot');
} catch (Zend_Feed_Exception $e) {
    // feed 导入失败
    echo "Exception caught importing feed: {$e->getMessage()}\n";
    exit;
}

// 初始化保存 channel 数据的数组
$channel = array(
    'title'       => $slashdotRss->title(),
    'link'        => $slashdotRss->link(),
    'description' => $slashdotRss->description(),
    'items'       => array()
    );

// 循环获得channel的item并存储到相关数组中
foreach ($slashdotRss as $item) {
    $channel['items'][] = array(
        'title'       => $item->title(),
        'link'        => $item->link(),
        'description' => $item->description()
        );
}
Zend_Feed
Zend_Feed
Zend Framework手册 中文版
导入Feeds
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Feed
  • 介绍
  • 导入Feeds
  • 从网页上获得Feed
  • RSS Feed的使用
  • Atom Feed的使用
  • 单个Atom条目的处理
  • 修改Feed和条目结构
  • 自定义Feed和条目类
  • Zend_Feed_Reader
  • Zend_Feed_Writer
  • Zend_Feed_Pubsubhubbub


导入Feeds - Zend Framework Manual

介绍
Zend_Feed
Zend Framework手册 中文版
从网页上获得Feed

导入Feeds

Zend_Feed 能让开发者轻松获得 Feeds 。如果你知道 Feeds 的URI，用Zend_Feed::import()方法就可以非常容易的获得它:

<?php
$feed = Zend_Feed::import('http://feeds.example.com/feedName');

你也能用Zend_Feed从一个文件或者一个PHP字符串变量来获得一个feed的内容:

<?php
// importing a feed from a text file
$feedFromFile = Zend_Feed::importFile('feed.xml');

// importing a feed from a PHP string variable
$feedFromPHP = Zend_Feed::importString($feedString);

在上面的例子中，根据feed类型的不同，一个从Zend_Feed_Abstract继承而来的类对象被返回。如果导入方法获得的是一个RSS feed，那么一个Zend_Feed_Rss对象将被返回(Seateng译注:以Factory模式实现)。另一方面，如果一个Atom feed被导入，那么将返回一个Zend_Feed_Atom对象。如果feed不可读或者不符合规范，导致导入失败那么Zend_Feed将抛出一个Zend_Feed_Exception异常。

定制 feeds

Zend_Feed 能让开发者轻松创建定制 feeds，只需要创建一个数组用 Zend_Feed 导入它。这个数组可以用 Zend_Feed::importArray() 或 Zend_Feed::importBuilder() 导入。最后数组用定制的实现了 Zend_Feed_Builder_Interface 数据源来处理。

导入定制的数组

<?php
// 从数组导入 feed
$atomFeedFromArray = Zend_Feed::importArray($array);

// 下面一行和上面相同；缺省地 Zend_Feed_Atom 实例被返回
$atomFeedFromArray = Zend_Feed::importArray($array, 'atom');

// 从数组导入 rss feed
$rssFeedFromArray = Zend_Feed::importArray($array, 'rss');

数组格式必须和这个结构一致：

<?php
array(
      'title'       => 'title of the feed', //required
      'link'        => 'canonical url to the feed', //required
      'lastUpdate'  => 'timestamp of the update date', // optional
      'published'   => 'timestamp of the publication date', //optional
      'charset'     => 'charset of the textual data', // required
      'description' => 'short description of the feed', //optional
      'author'      => 'author/publisher of the feed', //optional
      'email'       => 'email of the author', //optional
      'webmaster'   => 'email address for person responsible for technical issues' // optional, ignored if atom is used
      'copyright'   => 'copyright notice', //optional
      'image'       => 'url to image', //optional
      'generator'   => 'generator', // optional
      'language'    => 'language the feed is written in', // optional
      'ttl'         => 'how long in minutes a feed can be cached before refreshing', // optional, ignored if atom is used
      'rating'      => 'The PICS rating for the channel.', // optional, ignored if atom is used
      'cloud'       => array(
                             'domain'            => 'domain of the cloud, e.g. rpc.sys.com' // required
                             'port'              => 'port to connect to' // optional, default to 80
                             'path'              => 'path of the cloud, e.g. /RPC2' //required
                             'registerProcedure' => 'procedure to call, e.g. myCloud.rssPleaseNotify' // required
                             'protocol'          => 'protocol to use, e.g. soap or xml-rpc' // required
                             ), // a cloud to be notified of updates // optional, ignored if atom is used
      'textInput'   => array(
                             'title'       => 'the label of the Submit button in the text input area' // required,
                             'description' => 'explains the text input area' // required
                             'name'        => 'the name of the text object in the text input area' // required
                             'link'        => 'the URL of the CGI script that processes text input requests' // required
                             ) // a text input box that can be displayed with the feed // optional, ignored if atom is used
      'skipHours'   => array(
                             'hour in 24 format', // e.g 13 (1pm)
                             // up to 24 rows whose value is a number between 0 and 23
                             ) // Hint telling aggregators which hours they can skip // optional, ignored if atom is used
      'skipDays '   => array(
                             'a day to skip', // e.g Monday
                             // up to 7 rows whose value is a Monday, Tuesday, Wednesday, Thursday, Friday, Saturday or Sunday
                             ) // Hint telling aggregators which days they can skip // optional, ignored if atom is used
      'itunes'      => array(
                             'author'       => 'Artist column' // optional, default to the main author value
                             'owner'        => array(
                                                     'name' => 'name of the owner' // optional, default to main author value
                                                     'email' => 'email of the owner' // optional, default to main email value
                                                     ) // Owner of the podcast // optional
                             'image'        => 'album/podcast art' // optional, default to the main image value
                             'subtitle'     => 'short description' // optional, default to the main description value
                             'summary'      => 'longer description' // optional, default to the main description value
                             'block'        => 'Prevent an episode from appearing (yes|no)' // optional
                             'category'     => array(
                                                     array('main' => 'main category', // required
                                                           'sub'  => 'sub category' // optional
                                                           ),
                                                     // up to 3 rows
                                                     ) // 'Category column and in iTunes Music Store Browse' // required
                             'explicit'     => 'parental advisory graphic (yes|no|clean)' // optional
                             'keywords'     => 'a comma separated list of 12 keywords maximum' // optional
                             'new-feed-url' => 'used to inform iTunes of new feed URL location' // optional
                             ) // Itunes extension data // optional, ignored if atom is used
      'entries'     => array(
                             array(
                                   'title'        => 'title of the feed entry', //required
                                   'link'         => 'url to a feed entry', //required
                                   'description'  => 'short version of a feed entry', // only text, no html, required
                                   'guid'         => 'id of the article, if not given link value will used', //optional
                                   'content'      => 'long version', // can contain html, optional
                                   'lastUpdate'   => 'timestamp of the publication date', // optional
                                   'comments'     => 'comments page of the feed entry', // optional
                                   'commentRss'   => 'the feed url of the associated comments', // optional
                                   'source'       => array(
                                                           'title' => 'title of the original source' // required,
                                                           'url' => 'url of the original source' // required
                                                           ) // original source of the feed entry // optional
                                   'category'     => array(
                                                           array(
                                                                 'term' => 'first category label' // required,
                                                                 'scheme' => 'url that identifies a categorization scheme' // optional
                                                                 ),
                                                           array(
                                                                 //data for the second category and so on
                                                                 )
                                                           ) // list of the attached categories // optional
                                   'enclosure'    => array(
                                                           array(
                                                                 'url' => 'url of the linked enclosure' // required
                                                                 'type' => 'mime type of the enclosure' // optional
                                                                 'length' => 'length of the linked content in octets' // optional
                                                                 ),
                                                           array(
                                                                 //data for the second enclosure and so on
                                                                 )
                                                           ) // list of the enclosures of the feed entry // optional
                                   ),
                             array(
                                   //data for the second entry and so on
                                   )
                             )
       );

References:

  • RSS 2.0 规范： » RSS 2.0

  • Atom 规范：» RFC 4287

  • WFW 规范：» Well Formed Web

  • iTunes 规范： » iTunes Technical Specifications

导入定制的数据源

你可以从任何实现 Zend_Feed_Builder_Interface 的数据源创建 Zeed_Feed 实例，只需要实现 getHeader() 和 getEntries() 方法来和 Zend_Feed::importBuilder() 一起使用你的对象。作为一个简单的参考实现，你可以使用 Zend_Feed_Builder 它在构造器里带有一个数组，执行一些校验，然后可以在 importBuilder() 方法中使用。getHeader() 方法必须返回 Zend_Feed_Builder_Header 的实例， getEntries() 必须返回 Zend_Feed_Builder_Entry 实例的数组。

Note: Zend_Feed_Builder 作为具体实现来实现它的用法，（我们）鼓励用户写自己的类来实现 Zend_Feed_Builder_Interface。

Zend_Feed::importBuilder() 用法的例子：

<?php
// 从定制的 builder 源导入 feed
$atomFeedFromArray = Zend_Feed::importBuilder(new Zend_Feed_Builder($array));

// 和上面一样，缺省地 Zend_Feed_Atom 实例被返回
$atomFeedFromArray = Zend_Feed::importArray(new Zend_Feed_Builder($array), 'atom');

// 从定制的 builder 数组导入 rss feed
$rssFeedFromArray = Zend_Feed::importArray(new Zend_Feed_Builder($array), 'rss');

Dumping feed 内容

为了 dump Zend_Feed_Abstract 实例的内容，使用 send() 或 saveXml() 方法。

<?php
assert($feed instanceof Zend_Feed_Abstract);

// dump feed 到标准输出
print $feed->saveXML();

// 发送 http 头和 dump the feed
$feed->send();
介绍
Zend_Feed
Zend Framework手册 中文版
从网页上获得Feed
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Feed
  • 介绍
  • 导入Feeds
  • 从网页上获得Feed
  • RSS Feed的使用
  • Atom Feed的使用
  • 单个Atom条目的处理
  • 修改Feed和条目结构
  • 自定义Feed和条目类
  • Zend_Feed_Reader
  • Zend_Feed_Writer
  • Zend_Feed_Pubsubhubbub


从网页上获得Feed - Zend Framework Manual

导入Feeds
Zend_Feed
Zend Framework手册 中文版
RSS Feed的使用

从网页上获得Feed

在网页上与该页内容其相关的详细信息常被包含在一个用<link>标记关联的Feed中。Zend_Feed能让你用一个简单的方法提取一个页面上所有关联的Feed:

$feedArray = Zend_Feed::findFeeds('http://www.example.com/news.html');

findFeeds()方法返回一个Zend_Feed_Abstract对象数组，数组中的内容对应news.html页中所有用<link>关联到的Feed。根据每个feed类型的不同，$feedArray数组的下标变量可能是一个Zend_Feed_Rss对象的实例也可能是一个Zend_Feed_Atom对象的实例。但是如果服务器端响应HTTP 404或者feed不符合规范，那么Zend_Feed将抛出一个Zend_Feed_Exception异常。

导入Feeds
Zend_Feed
Zend Framework手册 中文版
RSS Feed的使用
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Feed
  • 介绍
  • 导入Feeds
  • 从网页上获得Feed
  • RSS Feed的使用
  • Atom Feed的使用
  • 单个Atom条目的处理
  • 修改Feed和条目结构
  • 自定义Feed和条目类
  • Zend_Feed_Reader
  • Zend_Feed_Writer
  • Zend_Feed_Pubsubhubbub


RSS Feed的使用 - Zend Framework Manual

从网页上获得Feed
Zend_Feed
Zend Framework手册 中文版
Atom Feed的使用

RSS Feed的使用

用一个Zend_Feed_Rss对象实例和一个Feed的URL来读取一个RSS Feed再简单不过了:

$channel = new Zend_Feed_Rss('http://rss.example.com/channelName');

如果在获得feed时发生任何错误，那么一个Zend_Feed_Exception异常将被抛出。

一旦你获得一个Feed对象，那么你就能在这个对象上直接访问任何RSS 标准定义的channel属性:

echo $channel->title();?>

注意函数语法。如果用 "getter" 的语法 ($obj->property) 取一个对象变量或是调用一个对象方法($obj->property())时，Zend_Feed将把这个变量名或方法名作为一个XML对象的属性处理(就像访问XML中的某个节点)。这样在取得指定的节点内容后还能访问其子节点。

如果RSS的channel有属性，那么可以用访问 PHP 数组的语法获得他们:

echo $channel->category['domain'];?>

因为XML的属性不能拥有子节点，所以不需要用方法的语法访问其属性。 values.

最常用的是您可以通过循环遍历Feed的条目来作些事情。Zend_Feed_Abstract 实现的是PHP 的Iterator接口，因此要打印channel中的文章标题可以像下面这样:

foreach ($channel as $item) {
    echo $item->title() . "\n";
}

如果你对RSS不是很熟，那这有一分关于RSS channel和各个RSS item(条目)标准元素的列表可能对你有帮助。

必须的 channel 元素:

  • title - channel 名

  • link - channel相关的站点URL

  • description - 一句或者若干关于channel的描述

可选的channel元素:

  • pubDate - 这份内容发布的时间，用 RFC 822 的日期格式

  • language - channel的书写语言

  • category - channel属于的一个或多个分类(用多个标记指名)

RSS 的<item> 组成没有严格的要求。但是title 或 description必须至少有一个。

常用的item元素:

  • title - item的标题

  • link - item的链接

  • description - item的概述

  • author - 作者Email

  • category - item所属的一个或者多个分类

  • comments - item相关评论的URL链接

  • pubDate - item的发布日期( RFC 822 日期格式)

在你的代码中，一个非空元素总是被能测到:

if ($item->propname()) {
    // ... proceed.
}

如果你用$item->propname代替$item->propname()，那么你将总是得到一个空对象使条件判断为TRUE，因此条件判断将失效。

更多信息，请参看RSS 2.0的官方说明:» http://blogs.law.harvard.edu/tech/rss。

从网页上获得Feed
Zend_Feed
Zend Framework手册 中文版
Atom Feed的使用
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Feed
  • 介绍
  • 导入Feeds
  • 从网页上获得Feed
  • RSS Feed的使用
  • Atom Feed的使用
  • 单个Atom条目的处理
  • 修改Feed和条目结构
  • 自定义Feed和条目类
  • Zend_Feed_Reader
  • Zend_Feed_Writer
  • Zend_Feed_Pubsubhubbub


Atom Feed的使用 - Zend Framework Manual

RSS Feed的使用
Zend_Feed
Zend Framework手册 中文版
单个Atom条目的处理

Atom Feed的使用

Zend_Feed_Atom在使用上有许多方法与Zend_Feed_Rss是大相径庭的。它提供了相同的方法访问Feed中的属性和遍历所有Feed中的所有条目。不同之处在于Atom协议结构自身。Atom作为RSS的继承者，它是一个更广泛的协议，在处理Feed中提供的所有内容方面它被设计的更加容易，RSS中的description标记在Atom中被分割成两个元素summary 和 content就是为了这个目的。

Example #1 Atom Feed的基本用法

读取一个Atom Feed并打印出每个条目的title 和 summary：

<?php

$feed = new Zend_Feed_Atom('http://atom.example.com/feed/');
echo 'The feed contains ' . $feed->count() . ' entries.' . "\n\n";
foreach ($feed as $entry) {
    echo '标题: ' . $entry->title() . "\n";
    echo '摘要: ' . $entry->summary() . "\n\n";
}

在Atom Feed中你能找到以下Feed属性：

  • title - Feed的标题, 和RSS中的channel标题一样

  • id - 在Atom中的每个Feed和条目都有一个唯一的标识符(id)

  • link - Feed可以有多个链接，它们之间用type属性区别

    当type="text/html"时与RSS的channel中的link是一样的。如果这个链接是一个在Feed中相同内容的候选版本，那么它将有一个rel="alternate"属性。

  • subtitle - Feed的描述，等同于RSS中的频道描述

    author->name() - Feed作者名

    author->email() - Feed作者的email地址

Atom 条目通常具有以下属性：

  • id - 条目唯一标识符

  • title - 条目标题，和RSS的item标题相同

  • link - 一个到另外一种格式的链接或者当前条目的一个候选观点

  • summary - 条目内容摘要

  • content - 条目的全部内容；如果feed就包含摘要可以被挑过

  • author - 有 name 和 email 子标记就像feed的author一样

  • published - 条目的发布日期(RFC 3339格式)

  • updated - 条目的最后更新日期(RFC 3339格式)

更多关于Atom的信息和丰富的资源，请参看» http://www.atomenabled.org/.

RSS Feed的使用
Zend_Feed
Zend Framework手册 中文版
单个Atom条目的处理
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Feed
  • 介绍
  • 导入Feeds
  • 从网页上获得Feed
  • RSS Feed的使用
  • Atom Feed的使用
  • 单个Atom条目的处理
  • 修改Feed和条目结构
  • 自定义Feed和条目类
  • Zend_Feed_Reader
  • Zend_Feed_Writer
  • Zend_Feed_Pubsubhubbub


单个Atom条目的处理 - Zend Framework Manual

Atom Feed的使用
Zend_Feed
Zend Framework手册 中文版
修改Feed和条目结构

单个Atom条目的处理

单个Atom <entry> 元素自身也是有效的。通常在Feed的URL后带上/<entryId>就是一个条目的URL。就像http://atom.example.com/feed/1， 我们就以上述的URL作为例子。

如果你想读取单个条目，你仍然可以使用Zend_Feed_Atom对象，它将自动创建一个匿名的Feed用来包含条目。

Example #1 读取Atom Feed的单个条目

<?php

$feed = new Zend_Feed_Atom('http://atom.example.com/feed/1');
echo 'The feed has: ' . $feed->count() . ' entry.';

$entry = $feed->current();

或者如果你确定只想访问文档的一个<entry>，那么你可以用条目对象直接访问：

Example #2 用条目对象直接访问Atom Feed的单个条目

<?php

$entry = new Zend_Feed_Entry_Atom('http://atom.example.com/feed/1');
echo $entry->title();
Atom Feed的使用
Zend_Feed
Zend Framework手册 中文版
修改Feed和条目结构
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Feed
  • 介绍
  • 导入Feeds
  • 从网页上获得Feed
  • RSS Feed的使用
  • Atom Feed的使用
  • 单个Atom条目的处理
  • 修改Feed和条目结构
  • 自定义Feed和条目类
  • Zend_Feed_Reader
  • Zend_Feed_Writer
  • Zend_Feed_Pubsubhubbub


修改Feed和条目结构 - Zend Framework Manual

单个Atom条目的处理
Zend_Feed
Zend Framework手册 中文版
自定义Feed和条目类

修改Feed和条目结构

Zend_Feed自然的语法既能扩展用于构建和修改Feed以及条目又能非常容易的读取它们。你能容易的把你的新的或者修改过的对象转化成一个结构完整的XML格式保存到文件或者发送到服务器。

Example #1 修改一个已存在的条目

$feed = new Zend_Feed_Atom('http://atom.example.com/feed/1');
$entry = $feed->current();

$entry->title = 'This is a new title';
$entry->author->email = 'my_email@example.com';

echo $entry->saveXML();

这段代码将输出一个新条目完整(包括<?xml ... > 声明)的包含所有必要命名空间的XML格式。

注意上面的代码即使条目中不存在一个author标记也能工作。在开始赋值之前你就能用多层的->访问你想要访问的内容了，如果必要程序将自动为你创建所有中间节点。

如果你想在你的条目中用一个与atom:, rss:, 或 osrss:不同的命名空间，你必须用Zend_Feed类的Zend_Feed::registerNamespace()方法注册你的命名空间。当你修改一个已存在的元素时，它将维持最初的命名空间。当添加一个新元素时，如果你不特别地指定别的命名空间则程序将使用默认的命名空间。

Example #2 用自定义的命名空间创建一个Atom条目元素

$entry = new Zend_Feed_Entry_Atom();
// Atom的id总是由服务器分配
$entry->title = 'my custom entry';
$entry->author->name = 'Example Author';
$entry->author->email = 'me@example.com';

// 完成自定义部分
Zend_Feed::registerNamespace('myns', 'http://www.example.com/myns/1.0');

$entry->{'myns:myelement_one'} = 'my first custom value';
$entry->{'myns:container_elt'}->part1 = 'first nested custom part';
$entry->{'myns:container_elt'}->part2 = 'second nested custom part';

echo $entry->saveXML();

?>
单个Atom条目的处理
Zend_Feed
Zend Framework手册 中文版
自定义Feed和条目类
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Feed
  • 介绍
  • 导入Feeds
  • 从网页上获得Feed
  • RSS Feed的使用
  • Atom Feed的使用
  • 单个Atom条目的处理
  • 修改Feed和条目结构
  • 自定义Feed和条目类
  • Zend_Feed_Reader
  • Zend_Feed_Writer
  • Zend_Feed_Pubsubhubbub


自定义Feed和条目类 - Zend Framework Manual

修改Feed和条目结构
Zend_Feed
Zend Framework手册 中文版
Zend_Feed_Reader

自定义Feed和条目类

最后，如果你想提供一个你自己的格式或者想更自动化的定义一个命名空间那么你可以扩展继承Zend_Feed类。

下面是一个用自定义Atom条目类处理myns:命名空间的例子。注意构造函数中已经为你调用了registerNamespace()，所以最终用户就可以完全不必当心命名空间了。

Example #1 用自定义的命名空间继承Atom条目类

<?php
/**
 * 自定义的条目类自动地识别feed URI(可选)
 * 并能自动添加额外的命名空间
 */
class MyEntry extends Zend_Feed_Entry_Atom
{

    public function __construct($uri = 'http://www.example.com/myfeed/',
                                $xml = null)
    {
        parent::__construct($uri, $xml);

        Zend_Feed::registerNamespace('myns', 'http://www.example.com/myns/1.0');
    }

    public function __get($var)
    {
        switch ($var) {
            case 'myUpdated':
                // Translate myUpdated to myns:updated.
                return parent::__get('myns:updated');

            default:
                return parent::__get($var);
            }
    }

    public function __set($var, $value)
    {
        switch ($var) {
            case 'myUpdated':
                // Translate myUpdated to myns:updated.
                parent::__set('myns:updated', $value);
                break;

            default:
                parent::__set($var, $value);
        }
    }

    public function __call($var, $unused)
    {
        switch ($var) {
            case 'myUpdated':
                // Translate myUpdated to myns:updated.
                return parent::__call('myns:updated', $unused);

            default:
                return parent::__call($var, $unused);
        }
    }
}

接下来你就可以直接实例化和设置myUpdated属性来使用这个类：

<?php
$entry = new MyEntry();
$entry->myUpdated = '2005-04-19T15:30';

// method-style call is handled by __call function
$entry->myUpdated();
// property-style call is handled by __get function
$entry->myUpdated;
修改Feed和条目结构
Zend_Feed
Zend Framework手册 中文版
Zend_Feed_Reader
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Feed
  • 介绍
  • 导入Feeds
  • 从网页上获得Feed
  • RSS Feed的使用
  • Atom Feed的使用
  • 单个Atom条目的处理
  • 修改Feed和条目结构
  • 自定义Feed和条目类
  • Zend_Feed_Reader
  • Zend_Feed_Writer
  • Zend_Feed_Pubsubhubbub


Zend_Feed_Reader - Zend Framework Manual

自定义Feed和条目类
Zend_Feed
Zend Framework手册 中文版
Zend_Feed_Writer

Zend_Feed_Reader

Introduction

Zend_Feed_Reader is a component used to consume RSS and Atom feeds of any version, including RDF/RSS 1.0, RSS 2.0 and Atom 0.3/1.0. The API for retrieving feed data is deliberately simple since Zend_Feed_Reader is capable of searching any feed of any type for the information requested through the API. If the typical elements containing this information are not present, it will adapt and fall back on a variety of alternative elements instead. This ability to choose from alternatives removes the need for users to create their own abstraction layer on top of the component to make it useful or have any in-depth knowledge of the underlying standards, current alternatives, and namespaced extensions.

Internally, Zend_Feed_Reader works almost entirely on the basis of making XPath queries against the feed XML's Document Object Model. The DOM is not exposed though a chained property API like Zend_Feed though the underlying DOMDocument, DOMElement and DOMXPath objects are exposed for external manipulation. This singular approach to parsing is consistent and the component offers a plugin system to add to the Feed and Entry level API by writing Extensions on a similar basis.

Performance is assisted in three ways. First of all, Zend_Feed_Reader supports caching using Zend_Cache to maintain a copy of the original feed XML. This allows you to skip network requests for a feed URI if the cache is valid. Second, the Feed and Entry level API is backed by an internal cache (non-persistant) so repeat API calls for the same feed will avoid additional DOM/XPath use. Thirdly, importing feeds from a URI can take advantage of HTTP Conditional GET requests which allow servers to issue an empty 304 response when the requested feed has not changed since the last time you requested it. In the final case, an instance of Zend_Cache will hold the last received feed along with the ETag and Last-Modified header values sent in the HTTP response.

In relation to Zend_Feed, Zend_Feed_Reader was formulated as a free standing replacement for Zend_Feed but it is not backwards compatible with Zend_Feed. Rather it is an alternative following a different ideology focused on being simple to use, flexible, consistent and extendable through the plugin system. Zend_Feed_Reader is also not capable of constructing feeds and delegates this responsibility to Zend_Feed_Writer, its sibling in arms.

Importing Feeds

Importing a feed with Zend_Feed_Reader is not that much different to Zend_Feed. Feeds can be imported from a string, file, URI or an instance of type Zend_Feed_Abstract. Importing from a URI can additionally utilise a HTTP Conditional GET request. If importing fails, an exception will be raised. The end result will be an object of type Zend_Feed_Reader_FeedInterface, the core implementations of which are Zend_Feed_Reader_Feed_Rss and Zend_Feed_Reader_Feed_Atom (Zend_Feed took all the short names!). Both objects support multiple (all existing) versions of these broad feed types.

In the following example, we import an RDF/RSS 1.0 feed and extract some basic information that can be saved to a database or elsewhere.

  1. $feed = Zend_Feed_Reader::import('http://www.planet-php.net/rdf/');
  2. $data = array(
  3.     'title'        => $feed->getTitle(),
  4.     'link'         => $feed->getLink(),
  5.     'dateModified' => $feed->getDateModified(),
  6.     'description'  => $feed->getDescription(),
  7.     'language'     => $feed->getLanguage(),
  8.     'entries'      => array(),
  9. );
  10.
  11. foreach ($feed as $entry) {
  12.     $edata = array(
  13.         'title'        => $entry->getTitle(),
  14.         'description'  => $entry->getDescription(),
  15.         'dateModified' => $entry->getDateModified(),
  16.         'authors'       => $entry->getAuthors(),
  17.         'link'         => $entry->getLink(),
  18.         'content'      => $entry->getContent()
  19.     );
  20.     $data['entries'][] = $edata;
  21. }

The example above demonstrates Zend_Feed_Reader's API, and it also demonstrates some of its internal operation. In reality, the RDF feed selected does not have any native date or author elements, however it does utilise the Dublin Core 1.1 module which offers namespaced creator and date elements. Zend_Feed_Reader falls back on these and similar options if no relevant native elements exist. If it absolutely cannot find an alternative it will return NULL, indicating the information could not be found in the feed. You should note that classes implementing Zend_Feed_Reader_FeedInterface also implement the SPL Iterator and Countable interfaces.

Feeds can also be imported from strings, files, and even objects of type Zend_Feed_Abstract.

  1. // from a URI
  2. $feed = Zend_Feed_Reader::import('http://www.planet-php.net/rdf/');
  3.
  4. // from a String
  5. $feed = Zend_Feed_Reader::importString($feedXmlString);
  6.
  7. // from a file
  8. $feed = Zend_Feed_Reader::importFile('./feed.xml');
  9.
  10. // from a Zend_Feed_Abstract object
  11. $zfeed = Zend_Feed::import('http://www.planet-php.net/atom/');
  12. $feed  = Zend_Feed_Reader::importFeed($zfeed);

Retrieving Underlying Feed and Entry Sources

Zend_Feed_Reader does its best not to stick you in a narrow confine. If you need to work on a feed outside of Zend_Feed_Reader, you can extract the base DOMDocument or DOMElement objects from any class, or even an XML string containing these. Also provided are methods to extract the current DOMXPath object (with all core and Extension namespaces registered) and the correct prefix used in all XPath queries for the current Feed or Entry. The basic methods to use (on any object) are saveXml(), getDomDocument(), getElement(), getXpath() and getXpathPrefix(). These will let you break free of Zend_Feed_Reader and do whatever else you want.

  • saveXml() returns an XML string containing only the element representing the current object.

  • getDomDocument() returns the DOMDocument object representing the entire feed (even if called from an Entry object).

  • getElement() returns the DOMElement of the current object (i.e. the Feed or current Entry).

  • getXpath() returns the DOMXPath object for the current feed (even if called from an Entry object) with the namespaces of the current feed type and all loaded Extensions pre-registered.

  • getXpathPrefix() returns the query prefix for the current object (i.e. the Feed or current Entry) which includes the correct XPath query path for that specific Feed or Entry.

Here's an example where a feed might include an RSS Extension not supported by Zend_Feed_Reader out of the box. Notably, you could write and register an Extension (covered later) to do this, but that's not always warranted for a quick check. You must register any new namespaces on the DOMXPath object before use unless they are registered by Zend_Feed_Reader or an Extension beforehand.

  1. $feed        = Zend_Feed_Reader::import('http://www.planet-php.net/rdf/');
  2. $xpathPrefix = $feed->getXpathPrefix();
  3. $xpath       = $feed->getXpath();
  4. $xpath->registerNamespace('admin', 'http://webns.net/mvcb/');
  5. $reportErrorsTo = $xpath->evaluate('string('
  6.                                  . $xpathPrefix
  7.                                  . '/admin:errorReportsTo)');
Warning

If you register an already registered namespace with a different prefix name to that used internally by Zend_Feed_Reader, it will break the internal operation of this component.

Cache Support and Intelligent Requests

Adding Cache Support to Zend_Feed_Reader

Zend_Feed_Reader supports using an instance of Zend_Cache to cache feeds (as XML) to avoid unnecessary network requests. Adding a cache is as simple here as it is for other Zend Framework components, create and configure your cache and then tell Zend_Feed_Reader to use it! The cache key used is "Zend_Feed_Reader_" followed by the MD5 hash of the feed's URI.

  1. $frontendOptions = array(
  2.    'lifetime' => 7200,
  3.    'automatic_serialization' => true
  4. );
  5. $backendOptions = array('cache_dir' => './tmp/');
  6. $cache = Zend_Cache::factory(
  7.     'Core', 'File', $frontendOptions, $backendOptions
  8. );
  9.
  10. Zend_Feed_Reader::setCache($cache);

Note: While it's a little off track, you should also consider adding a cache to Zend_Loader_PluginLoader which is used by Zend_Feed_Reader to load Extensions.

HTTP Conditional GET Support

The big question often asked when importing a feed frequently, is if it has even changed. With a cache enabled, you can add HTTP Conditional GET support to your arsenal to answer that question.

Using this method, you can request feeds from URIs and include their last known ETag and Last-Modified response header values with the request (using the If-None-Match and If-Modified-Since headers). If the feed on the server remains unchanged, you should receive a 304 response which tells Zend_Feed_Reader to use the cached version. If a full feed is sent in a response with a status code of 200, this means the feed has changed and Zend_Feed_Reader will parse the new version and save it to the cache. It will also cache the new ETag and Last-Modified header values for future use.

These "conditional" requests are not guaranteed to be supported by the server you request a URI of, but can be attempted regardless. Most common feed sources like blogs should however have this supported. To enable conditional requests, you will need to provide a cache to Zend_Feed_Reader.

  1. $frontendOptions = array(
  2.    'lifetime' => 86400,
  3.    'automatic_serialization' => true
  4. );
  5. $backendOptions = array('cache_dir' => './tmp/');
  6. $cache = Zend_Cache::factory(
  7.     'Core', 'File', $frontendOptions, $backendOptions
  8. );
  9.
  10. Zend_Feed_Reader::setCache($cache);
  11. Zend_Feed_Reader::useHttpConditionalGet();
  12.
  13. $feed = Zend_Feed_Reader::import('http://www.planet-php.net/rdf/');

In the example above, with HTTP Conditional GET requests enabled, the response header values for ETag and Last-Modified will be cached along with the feed. For the next 24hrs (the cache lifetime), feeds will only be updated on the cache if a non-304 response is received containing a valid RSS or Atom XML document.

If you intend on managing request headers from outside Zend_Feed_Reader, you can set the relevant If-None-Matches and If-Modified-Since request headers via the URI import method.

  1. $lastEtagReceived = '5e6cefe7df5a7e95c8b1ba1a2ccaff3d';
  2. $lastModifiedDateReceived = 'Wed, 08 Jul 2009 13:37:22 GMT';
  3. $feed = Zend_Feed_Reader::import(
  4.     $uri, $lastEtagReceived, $lastModifiedDateReceived
  5. );

Locating Feed URIs from Websites

These days, many websites are aware that the location of their XML feeds is not always obvious. A small RDF, RSS or Atom graphic helps when the user is reading the page, but what about when a machine visits trying to identify where your feeds are located? To assist in this, websites may point to their feeds using <link> tags in the <head> section of their HTML. To take advantage of this, you can use Zend_Feed_Reader to locate these feeds using the static findFeedLinks() method.

This method calls any URI and searches for the location of RSS, RDF and Atom feeds assuming the website's HTML contains the relevant links. It then returns a value object where you can check for the existence of a RSS, RDF or Atom feed URI.

The returned object is an ArrayObject subclass called Zend_Feed_Reader_Collection_FeedLink so you can cast it to an array, or iterate over it, to access all the detected links. However, as a simple shortcut, you can just grab the first RSS, RDF or Atom link using its public properties as in the example below. Otherwise, each element of the ArrayObject is a simple array with the keys "type" and "uri" where the type is one of "rdf", "rss" or "atom".

  1. $links = Zend_Feed_Reader::findFeedLinks('http://www.planet-php.net');
  2.
  3. if(isset($links->rdf)) {
  4.     echo $links->rdf, "\n"; // http://www.planet-php.org/rdf/
  5. }
  6. if(isset($links->rss)) {
  7.     echo $links->rss, "\n"; // http://www.planet-php.org/rss/
  8. }
  9. if(isset($links->atom)) {
  10.     echo $links->atom, "\n"; // http://www.planet-php.org/atom/
  11. }

Based on these links, you can then import from whichever source you wish in the usual manner.

This quick method only gives you one link for each feed type, but websites may indicate many links of any type. Perhaps it's a news site with a RSS feed for each news category. You can iterate over all links using the ArrayObject's iterator.

  1. $links = Zend_Feed_Reader::findFeedLinks('http://www.planet-php.net');
  2.
  3. foreach ($links as $link) {
  4.     echo $link['uri'], "\n";
  5. }

Attribute Collections

In an attempt to simplify return types, with Zend Framework 1.10 return types from the various feed and entry level methods may include an object of type Zend_Feed_Reader_Collection_CollectionAbstract. Despite the special class name which I'll explain below, this is just a simple subclass of SPL's ArrayObject.

The main purpose here is to allow the presentation of as much data as possible from the requested elements, while still allowing access to the most relevant data as a simple array. This also enforces a standard approach to returning such data which previously may have wandered between arrays and objects.

The new class type acts identically to ArrayObject with the sole addition being a new method getValues() which returns a simple flat array containing the most relevant information.

A simple example of this is Zend_Feed_Reader_FeedInterface::getCategories(). When used with any RSS or Atom feed, this method will return category data as a container object called Zend_Feed_Reader_Collection_Category. The container object will contain, per category, three fields of data: term, scheme and label. The "term" is the basic category name, often machine readable (i.e. plays nice with URIs). The scheme represents a categorisation scheme (usually a URI identifier) also known as a "domain" in RSS 2.0. The "label" is a human readable category name which supports html entities. In RSS 2.0, there is no label attribute so it is always set to the same value as the term for convenience.

To access category labels by themselves in a simple value array, you might commit to something like:

  1. $feed = Zend_Feed_Reader::import('http://www.example.com/atom.xml');
  2. $categories = $feed->getCategories();
  3. $labels = array();
  4. foreach ($categories as $cat) {
  5.     $labels[] = $cat['label']
  6. }

It's a contrived example, but the point is that the labels are tied up with other information.

However, the container class allows you to access the "most relevant" data as a simple array using the getValues() method. The concept of "most relevant" is obviously a judgement call. For categories it means the category labels (not the terms or schemes) while for authors it would be the authors' names (not their email addresses or URIs). The simple array is flat (just values) and passed through array_unique() to remove duplication.

  1. $feed = Zend_Feed_Reader::import('http://www.example.com/atom.xml');
  2. $categories = $feed->getCategories();
  3. $labels = $categories->getValues();

The above example shows how to extract only labels and nothing else thus giving simple access to the category labels without any additional work to extract that data by itself.

Retrieving Feed Information

Retrieving information from a feed (we'll cover entries/items in the next section though they follow identical principals) uses a clearly defined API which is exactly the same regardless of whether the feed in question is RSS/RDF/Atom. The same goes for sub-versions of these standards and we've tested every single RSS and Atom version. While the underlying feed XML can differ substantially in terms of the tags and elements they present, they nonetheless are all trying to convey similar information and to reflect this all the differences and wrangling over alternative tags are handled internally by Zend_Feed_Reader presenting you with an identical interface for each. Ideally, you should not have to care whether a feed is RSS or Atom so long as you can extract the information you want.

Note: While determining common ground between feed types is itself complex, it should be noted that RSS in particular is a constantly disputed "specification". This has its roots in the original RSS 2.0 document which contains ambiguities and does not detail the correct treatment of all elements. As a result, this component rigorously applies the RSS 2.0.11 Specification published by the RSS Advisory Board and its accompanying RSS Best Practices Profile. No other interpretation of RSS 2.0 will be supported though exceptions may be allowed where it does not directly prevent the application of the two documents mentioned above.

Of course, we don't live in an ideal world so there may be times the API just does not cover what you're looking for. To assist you, Zend_Feed_Reader offers a plugin system which allows you to write Extensions to expand the core API and cover any additional data you are trying to extract from feeds. If writing another Extension is too much trouble, you can simply grab the underlying DOM or XPath objects and do it by hand in your application. Of course, we really do encourage writing an Extension simply to make it more portable and reusable, and useful Extensions may be proposed to the Framework for formal addition.

Here's a summary of the Core API for Feeds. You should note it comprises not only the basic RSS and Atom standards, but also accounts for a number of included Extensions bundled with Zend_Feed_Reader. The naming of these Extension sourced methods remain fairly generic - all Extension methods operate at the same level as the Core API though we do allow you to retrieve any specific Extension object separately if required.

Feed Level API Methods
getId() | Returns a unique ID associated with this feed
getTitle() | Returns the title of the feed
getDescription() | Returns the text description of the feed.
getLink() | Returns a URI to the HTML website containing the same or similar information as this feed (i.e. if the feed is from a blog, it should provide the blog's URI where the HTML version of the entries can be read).
getFeedLink() | Returns the URI of this feed, which may be the same as the URI used to import the feed. There are important cases where the feed link may differ because the source URI is being updated and is intended to be removed in the future.
getAuthors() | Returns an object of type Zend_Feed_Reader_Collection_Author which is an ArrayObject whose elements are each simple arrays containing any combination of the keys "name", "email" and "uri". Where irrelevant to the source data, some of these keys may be omitted.
getAuthor(integer $index = 0) | Returns either the first author known, or with the optional $index parameter any specific index on the array of Authors as described above (returning NULL if an invalid index).
getDateCreated() | Returns the date on which this feed was created. Generally only applicable to Atom where it represents the date the resource described by an Atom 1.0 document was created. The returned date will be a Zend_Date object.
getDateModified() | Returns the date on which this feed was last modified. The returned date will be a Zend_Date object.
getLanguage() | Returns the language of the feed (if defined) or simply the language noted in the XML document.
getGenerator() | Returns the generator of the feed, e.g. the software which generated it. This may differ between RSS and Atom since Atom defines a different notation.
getCopyright() | Returns any copyright notice associated with the feed.
getHubs() | Returns an array of all Hub Server URI endpoints which are advertised by the feed for use with the Pubsubhubbub Protocol, allowing subscriptions to the feed for real-time updates.
getCategories() | Returns a Zend_Feed_Reader_Collection_Category object containing the details of any categories associated with the overall feed. The supported fields include "term" (the machine readable category name), "scheme" (the categorisation scheme/domain for this category), and "label" (a html decoded human readable category name). Where any of the three fields are absent from the field, they are either set to the closest available alternative or, in the case of "scheme", set to NULL.

Given the variety of feeds in the wild, some of these methods will undoubtedly return NULL indicating the relevant information couldn't be located. Where possible, Zend_Feed_Reader will fall back on alternative elements during its search. For example, searching an RSS feed for a modification date is more complicated than it looks. RSS 2.0 feeds should include a <lastBuildDate> tag and/or a <pubDate> element. But what if it doesn't, maybe this is an RSS 1.0 feed? Perhaps it instead has an <atom:updated> element with identical information (Atom may be used to supplement RSS's syntax)? Failing that, we could simply look at the entries, pick the most recent, and use its <pubDate> element. Assuming it exists... Many feeds also use Dublin Core 1.0/1.1 <dc:date> elements for feeds/entries. Or we could find Atom lurking again.

The point is, Zend_Feed_Reader was designed to know this. When you ask for the modification date (or anything else), it will run off and search for all these alternatives until it either gives up and returns NULL, or finds an alternative that should have the right answer.

In addition to the above methods, all Feed objects implement methods for retrieving the DOM and XPath objects for the current feeds as described earlier. Feed objects also implement the SPL Iterator and Countable interfaces. The extended API is summarised below.

Extended Feed Level API Methods
getDomDocument() | Returns the parent DOMDocument object for the entire source XML document
getElement() | Returns the current feed level DOMElement object
saveXml() | Returns a string containing an XML document of the entire feed element (this is not the original document but a rebuilt version)
getXpath() | Returns the DOMXPath object used internally to run queries on the DOMDocument object (this includes core and Extension namespaces pre-registered)
getXpathPrefix() | Returns the valid DOM path prefix prepended to all XPath queries matching the feed being queried
getEncoding() | Returns the encoding of the source XML document (note: this cannot account for errors such as the server sending documents in a different encoding). Where not defined, the default UTF-8 encoding of Unicode is applied.
count() | Returns a count of the entries or items this feed contains (implements SPL Countable interface)
current() | Returns either the current entry (using the current index from key())
key() | Returns the current entry index
next() | Increments the entry index value by one
rewind() | Resets the entry index to 0
valid() | Checks that the current entry index is valid, i.e. it does fall below 0 and does not exceed the number of entries existing.
getExtensions() | Returns an array of all Extension objects loaded for the current feed (note: both feed-level and entry-level Extensions exist, and only feed-level Extensions are returned here). The array keys are of the form {ExtensionName}_Feed.
getExtension(string $name) | Returns an Extension object for the feed registered under the provided name. This allows more fine-grained access to Extensions which may otherwise be hidden within the implementation of the standard API methods.
getType() | Returns a static class constant (e.g. Zend_Feed_Reader::TYPE_ATOM_03, i.e. Atom 0.3) indicating exactly what kind of feed is being consumed.

Retrieving Entry/Item Information

Retrieving information for specific entries or items (depending on whether you speak Atom or RSS) is identical to feed level data. Accessing entries is simply a matter of iterating over a Feed object or using the SPL Iterator interface Feed objects implement and calling the appropriate method on each.

Entry Level API Methods
getId() | Returns a unique ID for the current entry.
getTitle() | Returns the title of the current entry.
getDescription() | Returns a description of the current entry.
getLink() | Returns a URI to the HTML version of the current entry.
getPermaLink() | Returns the permanent link to the current entry. In most cases, this is the same as using getLink().
getAuthors() | Returns an object of type Zend_Feed_Reader_Collection_Author which is an ArrayObject whose elements are each simple arrays containing any combination of the keys "name", "email" and "uri". Where irrelevant to the source data, some of these keys may be omitted.
getAuthor(integer $index = 0) | Returns either the first author known, or with the optional $index parameter any specific index on the array of Authors as described above (returning NULL if an invalid index).
getDateCreated() | Returns the date on which the current entry was created. Generally only applicable to Atom where it represents the date the resource described by an Atom 1.0 document was created.
getDateModified() | Returns the date on which the current entry was last modified
getContent() | Returns the content of the current entry (this has any entities reversed if possible assuming the content type is HTML). The description is returned if a separate content element does not exist.
getEnclosure() | Returns an array containing the value of all attributes from a multi-media <enclosure> element including as array keys: url, length, type. In accordance with the RSS Best Practices Profile of the RSS Advisory Board, no support is offers for multiple enclosures since such support forms no part of the RSS specification.
getCommentCount() | Returns the number of comments made on this entry at the time the feed was last generated
getCommentLink() | Returns a URI pointing to the HTML page where comments can be made on this entry
getCommentFeedLink([string $type = 'atom'|'rss']) | Returns a URI pointing to a feed of the provided type containing all comments for this entry (type defaults to Atom/RSS depending on current feed type).
getCategories() | Returns a Zend_Feed_Reader_Collection_Category object containing the details of any categories associated with the entry. The supported fields include "term" (the machine readable category name), "scheme" (the categorisation scheme/domain for this category), and "label" (a html decoded human readable category name). Where any of the three fields are absent from the field, they are either set to the closest available alternative or, in the case of "scheme", set to NULL.

The extended API for entries is identical to that for feeds with the exception of the Iterator methods which are not needed here.

Caution

There is often confusion over the concepts of modified and created dates. In Atom, these are two clearly defined concepts (so knock yourself out) but in RSS they are vague. RSS 2.0 defines a single <pubDate> element which typically refers to the date this entry was published, i.e. a creation date of sorts. This is not always the case, and it may change with updates or not. As a result, if you really want to check whether an entry has changed, don't rely on the results of getDateModified(). Instead, consider tracking the MD5 hash of three other elements concatenated, e.g. using getTitle(), getDescription() and getContent(). If the entry was truly updated, this hash computation will give a different result than previously saved hashes for the same entry. This is obviously content oriented, and will not assist in detecting changes to other relevant elements. Atom feeds should not require such steps.

Further muddying the waters, dates in feeds may follow different standards. Atom and Dublin Core dates should follow ISO 8601, and RSS dates should follow RFC 822 or RFC 2822 which is also common. Date methods will throw an exception if Zend_Date cannot load the date string using one of the above standards, or the PHP recognised possibilities for RSS dates.

Warning

The values returned from these methods are not validated. This means users must perform validation on all retrieved data including the filtering of any HTML such as from getContent() before it is output from your application. Remember that most feeds come from external sources, and therefore the default assumption should be that they cannot be trusted.

Extended Entry Level API Methods
getDomDocument() | Returns the parent DOMDocument object for the entire feed (not just the current entry)
getElement() | Returns the current entry level DOMElement object
getXpath() | Returns the DOMXPath object used internally to run queries on the DOMDocument object (this includes core and Extension namespaces pre-registered)
getXpathPrefix() | Returns the valid DOM path prefix prepended to all XPath queries matching the entry being queried
getEncoding() | Returns the encoding of the source XML document (note: this cannot account for errors such as the server sending documents in a different encoding). The default encoding applied in the absence of any other is the UTF-8 encoding of Unicode.
getExtensions() | Returns an array of all Extension objects loaded for the current entry (note: both feed-level and entry-level Extensions exist, and only entry-level Extensions are returned here). The array keys are in the form {ExtensionName}_Entry.
getExtension(string $name) | Returns an Extension object for the entry registered under the provided name. This allows more fine-grained access to Extensions which may otherwise be hidden within the implementation of the standard API methods.
getType() | Returns a static class constant (e.g. Zend_Feed_Reader::TYPE_ATOM_03, i.e. Atom 0.3) indicating exactly what kind of feed is being consumed.

Extending Feed and Entry APIs

Extending Zend_Feed_Reader allows you to add methods at both the feed and entry level which cover the retrieval of information not already supported by Zend_Feed_Reader. Given the number of RSS and Atom extensions that exist, this is a good thing since Zend_Feed_Reader couldn't possibly add everything.

There are two types of Extensions possible, those which retrieve information from elements which are immediate children of the root element (e.g. <channel> for RSS or <feed> for Atom) and those who retrieve information from child elements of an entry (e.g. <item> for RSS or <entry> for Atom). On the filesystem these are grouped as classes within a namespace based on the extension standard's name. For example, internally we have Zend_Feed_Reader_Extension_DublinCore_Feed and Zend_Feed_Reader_Extension_DublinCore_Entry classes which are two Extensions implementing Dublin Core 1.0/1.1 support.

Extensions are loaded into Zend_Feed_Reader using Zend_Loader_PluginLoader, so their operation will be familiar from other Zend Framework components. Zend_Feed_Reader already bundles a number of these Extensions, however those which are not used internally and registered by default (so called Core Extensions) must be registered to Zend_Feed_Reader before they are used. The bundled Extensions include:

Core Extensions (pre-registered)
DublinCore (Feed and Entry) | Implements support for Dublin Core Metadata Element Set 1.0 and 1.1
Content (Entry only) | Implements support for Content 1.0
Atom (Feed and Entry) | Implements support for Atom 0.3 and Atom 1.0
Slash | Implements support for the Slash RSS 1.0 module
WellFormedWeb | Implements support for the Well Formed Web CommentAPI 1.0
Thread | Implements support for Atom Threading Extensions as described in RFC 4685
Podcast | Implements support for the Podcast 1.0 DTD from Apple

The Core Extensions are somewhat special since they are extremely common and multi-faceted. For example, we have a Core Extension for Atom. Atom is implemented as an Extension (not just a base class) because it doubles as a valid RSS module - you can insert Atom elements into RSS feeds. I've even seen RDF feeds which use a lot of Atom in place of more common Extensions like Dublin Core.

Non-Core Extensions (must register manually)
Syndication | Implements Syndication 1.0 support for RSS feeds
CreativeCommons | A RSS module that adds an element at the <channel> or <item> level that specifies which Creative Commons license applies.

The additional non-Core Extensions are offered but not registered to Zend_Feed_Reader by default. If you want to use them, you'll need to tell Zend_Feed_Reader to load them in advance of importing a feed. Additional non-Core Extensions will be included in future iterations of the component.

Registering an Extension with Zend_Feed_Reader, so it is loaded and its API is available to Feed and Entry objects, is a simple affair using the Zend_Loader_PluginLoader. Here we register the optional Slash Extension, and discover that it can be directly called from the Entry level API without any effort. Note that Extension names are case sensitive and use camel casing for multiple terms.

  1. Zend_Feed_Reader::registerExtension('Syndication');
  2. $feed = Zend_Feed_Reader::import('http://rss.slashdot.org/Slashdot/slashdot');
  3. $updatePeriod = $feed->current()->getUpdatePeriod();

In the simple example above, we checked how frequently a feed is being updated using the getUpdatePeriod() method. Since it's not part of Zend_Feed_Reader's core API, it could only be a method supported by the newly registered Syndication Extension.

As you can also notice, the new methods from Extensions are accessible from the main API using PHP's magic methods. As an alternative, you can also directly access any Extension object for a similar result as seen below.

  1. Zend_Feed_Reader::registerExtension('Syndication');
  2. $feed = Zend_Feed_Reader::import('http://rss.slashdot.org/Slashdot/slashdot');
  3. $syndication = $feed->getExtension('Syndication');
  4. $updatePeriod = $syndication->getUpdatePeriod();

Writing Zend_Feed_Reader Extensions

Inevitably, there will be times when the Zend_Feed_Reader API is just not capable of getting something you need from a feed or entry. You can use the underlying source objects, like DOMDocument, to get these by hand however there is a more reusable method available by writing Extensions supporting these new queries.

As an example, let's take the case of a purely fictitious corporation named Jungle Books. Jungle Books have been publishing a lot of reviews on books they sell (from external sources and customers), which are distributed as an RSS 2.0 feed. Their marketing department realises that web applications using this feed cannot currently figure out exactly what book is being reviewed. To make life easier for everyone, they determine that the geek department needs to extend RSS 2.0 to include a new element per entry supplying the ISBN-10 or ISBN-13 number of the publication the entry concerns. They define the new <isbn> element quite simply with a standard name and namespace URI:

  1. JungleBooks 1.0:
  2. http://example.com/junglebooks/rss/module/1.0/

A snippet of RSS containing this extension in practice could be something similar to:

  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <rss version="2.0"
  3.    xmlns:content="http://purl.org/rss/1.0/modules/content/"
  4.    xmlns:jungle="http://example.com/junglebooks/rss/module/1.0/">
  5. <channel>
  6.     <title>Jungle Books Customer Reviews</title>
  7.     <link>http://example.com/junglebooks</link>
  8.     <description>Many book reviews!</description>
  9.     <pubDate>Fri, 26 Jun 2009 19:15:10 GMT</pubDate>
  10.     <jungle:dayPopular>
  11.         http://example.com/junglebooks/book/938
  12.     </jungle:dayPopular>
  13.     <item>
  14.         <title>Review Of Flatland: A Romance of Many Dimensions</title>
  15.         <link>http://example.com/junglebooks/review/987</link>
  16.         <author>Confused Physics Student</author>
  17.         <content:encoded>
  18.         A romantic square?!
  19.         </content:encoded>
  20.         <pubDate>Thu, 25 Jun 2009 20:03:28 -0700</pubDate>
  21.         <jungle:isbn>048627263X</jungle:isbn>
  22.     </item>
  23. </channel>
  24. </rss>

Implementing this new ISBN element as a simple entry level extension would require the following class (using your own class namespace outside of Zend).

  1. class My_FeedReader_Extension_JungleBooks_Entry
  2.     extends Zend_Feed_Reader_Extension_EntryAbstract
  3. {
  4.     public function getIsbn()
  5.     {
  6.         if (isset($this->_data['isbn'])) {
  7.             return $this->_data['isbn'];
  8.         }
  9.         $isbn = $this->_xpath->evaluate(
  10.             'string(' . $this->getXpathPrefix() . '/jungle:isbn)'
  11.         );
  12.         if (!$isbn) {
  13.             $isbn = null;
  14.         }
  15.         $this->_data['isbn'] = $isbn;
  16.         return $this->_data['isbn'];
  17.     }
  18.
  19.     protected function _registerNamespaces()
  20.     {
  21.         $this->_xpath->registerNamespace(
  22.             'jungle', 'http://example.com/junglebooks/rss/module/1.0/'
  23.         );
  24.     }
  25. }

This extension is easy enough to follow. It creates a new method getIsbn() which runs an XPath query on the current entry to extract the ISBN number enclosed by the <jungle:isbn> element. It can optionally store this to the internal non-persistent cache (no need to keep querying the DOM if it's called again on the same entry). The value is returned to the caller. At the end we have a protected method (it's abstract so it must exist) which registers the Jungle Books namespace for their custom RSS module. While we call this an RSS module, there's nothing to prevent the same element being used in Atom feeds - and all Extensions which use the prefix provided by getXpathPrefix() are actually neutral and work on RSS or Atom feeds with no extra code.

Since this Extension is stored outside of Zend Framework, you'll need to register the path prefix for your Extensions so Zend_Loader_PluginLoader can find them. After that, it's merely a matter of registering the Extension, if it's not already loaded, and using it in practice.

  1. if(!Zend_Feed_Reader::isRegistered('JungleBooks')) {
  2.     Zend_Feed_Reader::addPrefixPath(
  3.         '/path/to/My/FeedReader/Extension', 'My_FeedReader_Extension'
  4.     );
  5.     Zend_Feed_Reader::registerExtension('JungleBooks');
  6. }
  7. $feed = Zend_Feed_Reader::import('http://example.com/junglebooks/rss');
  8.
  9. // ISBN for whatever book the first entry in the feed was concerned with
  10. $firstIsbn = $feed->current()->getIsbn();

Writing a feed level Extension is not much different. The example feed from earlier included an unmentioned <jungle:dayPopular> element which Jungle Books have added to their standard to include a link to the day's most popular book (in terms of visitor traffic). Here's an Extension which adds a getDaysPopularBookLink() method to the feel level API.

  1. class My_FeedReader_Extension_JungleBooks_Feed
  2.     extends Zend_Feed_Reader_Extension_FeedAbstract
  3. {
  4.     public function getDaysPopularBookLink()
  5.     {
  6.         if (isset($this->_data['dayPopular'])) {
  7.             return $this->_data['dayPopular'];
  8.         }
  9.         $dayPopular = $this->_xpath->evaluate(
  10.             'string(' . $this->getXpathPrefix() . '/jungle:dayPopular)'
  11.         );
  12.         if (!$dayPopular) {
  13.             $dayPopular = null;
  14.         }
  15.         $this->_data['dayPopular'] = $dayPopular;
  16.         return $this->_data['dayPopular'];
  17.     }
  18.
  19.     protected function _registerNamespaces()
  20.     {
  21.         $this->_xpath->registerNamespace(
  22.             'jungle', 'http://example.com/junglebooks/rss/module/1.0/'
  23.         );
  24.     }
  25. }

Let's repeat the last example using a custom Extension to show the method being used.

  1. if(!Zend_Feed_Reader::isRegistered('JungleBooks')) {
  2.     Zend_Feed_Reader::addPrefixPath(
  3.         '/path/to/My/FeedReader/Extension', 'My_FeedReader_Extension'
  4.     );
  5.     Zend_Feed_Reader::registerExtension('JungleBooks');
  6. }
  7. $feed = Zend_Feed_Reader::import('http://example.com/junglebooks/rss');
  8.
  9. // URI to the information page of the day's most popular book with visitors
  10. $daysPopularBookLink = $feed->getDaysPopularBookLink();
  11.
  12. // ISBN for whatever book the first entry in the feed was concerned with
  13. $firstIsbn = $feed->current()->getIsbn();

Going through these examples, you'll note that we don't register feed and entry Extensions separately. Extensions within the same standard may or may not include both a feed and entry class, so Zend_Feed_Reader only requires you to register the overall parent name, e.g. JungleBooks, DublinCore, Slash. Internally, it can check at what level Extensions exist and load them up if found. In our case, we have a full set of Extensions now: JungleBooks_Feed and JungleBooks_Entry.

自定义Feed和条目类
Zend_Feed
Zend Framework手册 中文版
Zend_Feed_Writer
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Feed
  • 介绍
  • 导入Feeds
  • 从网页上获得Feed
  • RSS Feed的使用
  • Atom Feed的使用
  • 单个Atom条目的处理
  • 修改Feed和条目结构
  • 自定义Feed和条目类
  • Zend_Feed_Reader
  • Zend_Feed_Writer
  • Zend_Feed_Pubsubhubbub


Zend_Feed_Writer - Zend Framework Manual

Zend_Feed_Reader
Zend_Feed
Zend Framework手册 中文版
Zend_Feed_Pubsubhubbub

Zend_Feed_Writer

Introduction

Zend_Feed_Writer is the sibling component to Zend_Feed_Reader responsible for generating feeds for output. It supports the Atom 1.0 specification (RFC 4287) and RSS 2.0 as specified by the RSS Advisory Board (RSS 2.0.11). It does not deviate from these standards. It does, however, offer a simple Extension system which allows for any extension/module for either of these two specifications to be implemented if they are not provided out of the box.

In many ways, Zend_Feed_Writer is the inverse of Zend_Feed_Reader. Where Zend_Feed_Reader focused on providing an easy to use architecture fronted by getter methods, Zend_Feed_Writer is fronted by similarly named setters or mutators. This ensures the API won't pose a learning curve to anyone familiar with Zend_Feed_Reader.

As a result of this design, the rest may even be obvious. Behind the scenes, data set on any Zend_Feed_Reader object is translated at render time onto a DOMDocument object using the necessary feed elements. For each supported feed type there is both an Atom 1.0 and RSS 2.0 renderer. Using a DOMDocument rather a templating solution has numerous advantages, the most obvious being the ability to export the DOMDocument for additional processing and relying on PHP DOM for correct and valid rendering.

As with Zend_Feed_Reader, Zend_Feed_Writer is a standalone replacement for Zend_Feed's Builder architecture and is not compatible with those classes.

Architecture

The architecture of Zend_Feed_Writer is very simple. It has two core sets of classes: containers and renderers.

The containers include the Zend_Feed_Writer_Feed and Zend_Feed_Writer_Entry classes. The Entry classes can be attached to any Feed class. The sole purpose of these containers is to collect data about the feed to generate using a simple interface of setter methods. These methods perform some data validity testing. For example, it will validate any passed URIs, dates, etc. These checks are not tied to any of the feed standards. The container objects also contain methods to allow for fast rendering and export of the final feed, and these can be reused at will.

While there are two data containers, there are four renderers - two matching container renderers per support feed type. The renderer accept a container, and based on its content attempt to generate a valid feed. If the renderer is unable to generate a valid feed, perhaps due to the container missing an obligatory data point, it will report this by throwing an Exception. While it is possible to ignore Exceptions, this removes the default safeguard of ensuring you have sufficient data set to render a wholly valid feed.

Due to the system being divided between data containers and renderers, it can make Extensions somewhat interesting. A typical Extension offering namespaced feed and entry level elements, must itself reflect the exact same architecture, i.e. offer feed and entry level data containers, and matching renderers. There is, fortunately, no complex integration work required since all Extension classes are simply registered and automatically used by the core classes. We'll meet Extensions in more detail at the end of this section.

Getting Started

Using Zend_Feed_Reader is as simple as setting data and triggering the renderer. Here is an example to generate a minimal Atom 1.0 feed.

  1. /**
  2. * Create the parent feed
  3. */
  4. $feed = new Zend_Feed_Writer_Feed;
  5. $feed->setTitle('Paddy\'s Blog');
  6. $feed->setLink('http://www.example.com');
  7. $feed->setFeedLink('http://www.example.com/atom', 'atom');
  8. $feed->addAuthor(array(
  9.     'name'  => 'Paddy',
  10.     'email' => 'paddy@example.com',
  11.     'uri'   => 'http://www.example.com',
  12. ));
  13. $feed->setDateModified(time());
  14. $feed->addHub('http://pubsubhubbub.appspot.com/');
  15.
  16. /**
  17. * Add one or more entries. Note that entries must
  18. * be manually added once created.
  19. */
  20. $entry = $feed->createEntry();
  21. $entry->setTitle('All Your Base Are Belong To Us');
  22. $entry->setLink('http://www.example.com/all-your-base-are-belong-to-us');
  23. $entry->addAuthor(array(
  24.     'name'  => 'Paddy',
  25.     'email' => 'paddy@example.com',
  26.     'uri'   => 'http://www.example.com',
  27. ));
  28. $entry->setDateModified(time());
  29. $entry->setDateCreated(time());
  30. $entry->setDescription('Exposing the difficultly of porting games to English.');
  31. $entry->setContent('I am not writing the article. The example is long enough as is ;).');
  32. $feed->addEntry($entry);
  33.
  34. /**
  35. * Render the resulting feed to Atom 1.0 and assign to $out.
  36. * You can substitute "atom" with "rss" to generate an RSS 2.0 feed.
  37. */
  38. $out = $feed->export('atom');

The output rendered should be as follows:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <feed xmlns="http://www.w3.org/2005/Atom">
  3.     <title type="text">Paddy's Blog</title>
  4.     <subtitle type="text">Writing about PC Games since 176 BC.</subtitle>
  5.     <updated>2009-12-14T20:28:18+00:00</updated>
  6.     <generator uri="http://framework.zend.com" version="1.10.0alpha">
  7.         Zend_Feed_Writer
  8.     </generator>
  9.     <link rel="alternate" type="text/html" href="http://www.example.com"/>
  10.     <link rel="self" type="application/atom+xml" href="http://www.example.com/atom"/>
  11.     <id>http://www.example.com</id>
  12.     <author>
  13.         <name>Paddy</name>
  14.         <email>paddy@example.com</email>
  15.         <uri>http://www.example.com</uri>
  16.     </author>
  17.     <link rel="hub" href="http://pubsubhubbub.appspot.com/"/>
  18.     <entry>
  19.         <title type="html"><![CDATA[All Your Base Are Belong To Us]]></title>
  20.         <summary type="html">
  21.             <![CDATA[Exposing the difficultly of porting games to English.]]>
  22.         </summary>
  23.         <published>2009-12-14T20:28:18+00:00</published>
  24.         <updated>2009-12-14T20:28:18+00:00</updated>
  25.         <link rel="alternate" type="text/html" href="http://www.example.com/all-your-base-are-belong-to-us"/>
  26.         <id>http://www.example.com/all-your-base-are-belong-to-us</id>
  27.         <author>
  28.         <name>Paddy</name>
  29.         <email>paddy@example.com</email>
  30.         <uri>http://www.example.com</uri>
  31.         </author>
  32.         <content type="html">
  33.             <![CDATA[I am not writing the article. The example is long enough as is ;).]]>
  34.         </content>
  35.     </entry>
  36. </feed>

This is a perfectly valid Atom 1.0 example. It should be noted that omitting an obligatory point of data, such as a title, will trigger an Exception when rendering as Atom 1.0. This will differ for RSS 2.0 since a title may be omitted so long as a description is present. This gives rise to Exceptions that differ between the two standards depending on the renderer in use. By design, Zend_Feed_Writer will not render an invalid feed for either standard unless the end-user deliberately elects to ignore all Exceptions.

Setting Feed Data Points

Before you can render a feed, you must first setup the data necessary for the feed being rendered. This utilises a simple setter style API which doubles as an initial method for validating the data being set. By design, the API closely matches that for Zend_Feed_Reader to avoid undue confusion and uncertainty.

Zend_Feed_Writer offers this API via its data container classes Zend_Feed_Writer_Feed and Zend_Feed_Writer_Entry. These classes merely store all feed data in type-agnostic manner, meaning you may reuse any data container with any renderer without requiring additional work. Both classes are also amenable to Extensions, meaning that an Extension may define its own container classes which are registered to the base container classes as extensions, and are checked when any method call triggers the base container's __call() method.

Here's a summary of the Core API for Feeds. You should note it comprises not only the basic RSS and Atom standards, but also accounts for a number of included Extensions bundled with Zend_Feed_Writer. The naming of these Extension sourced methods remain fairly generic - all Extension methods operate at the same level as the Core API though we do allow you to retrieve any specific Extension object separately if required.

Feed Level API Methods
setId() | Set a unique ID associated with this feed. For Atom 1.0 this is an atom:id element, whereas for RSS 2.0 it is added as a guid element. These are optional so long as a link is added, i.e. the link is set as the ID.
setTitle() | Set the title of the feed.
setDescription() | Set the text description of the feed.
setLink() | Set a URI to the HTML website containing the same or similar information as this feed (i.e. if the feed is from a blog, it should provide the blog's URI where the HTML version of the entries can be read).
setFeedLinks() | Add a link to an XML feed, whether the feed being generated or an alternate URI pointing to the same feed but in a different format. At a minimum, it is recommended to include a link to the feed being generated so it has an identifiable final URI allowing a client to track its location changes without necessitating constant redirects. The parameter is an array of arrays, where each sub-array contains the keys "type" and "uri". The type should be one of "atom", "rss", or "rdf". If a type is omitted, it defaults to the type used when rendering the feed.
setAuthors() | Sets the data for authors. The parameter is an array of arrays where each sub-array may contain the keys "name", "email" and "uri". The "uri" value is only applicable for Atom feeds since RSS contains no facility to show it. For RSS 2.0, rendering will create two elements - an author element containing the email reference with the name in brackets, and a Dublin Core creator element only containing the name.
setAuthor() | Sets the data for a single author following the same format as described above for a single sub-array.
setDateCreated() | Sets the date on which this feed was created. Generally only applicable to Atom where it represents the date the resource described by an Atom 1.0 document was created. The expected parameter may be a UNIX timestamp or a Zend_Date object.
getDateModified() | Sets the date on which this feed was last modified. The expected parameter may be a UNIX timestamp or a Zend_Date object.
setLanguage() | Sets the language of the feed. This will be omitted unless set.
getGenerator() | Allows the setting of a generator. The parameter should be an array containing the keys "name", "version" and "uri". If omitted a default generator will be added referencing Zend_Feed_Writer, the current Zend Framework version and the Framework's URI.
setCopyright() | Sets a copyright notice associated with the feed.
setHubs() | Accepts an array of Pubsubhubbub Hub Endpoints to be rendered in the feed as Atom links so that PuSH Subscribers may subscribe to your feed. Note that you must implement a Pubsubhubbub Publisher in order for real-time updates to be enabled. A Publisher may be implemented using Zend_Feed_Pubsubhubbub_Publisher.
setCategories() | Accepts an array of categories for rendering, where each element is itself an array whose possible keys include "term", "label" and "scheme". The "term" is a typically a category name suitable for inclusion in a URI. The "label" may be a human readable category name supporting special characters (it is encoded during rendering) and is a required key. The "scheme" (called the domain in RSS) is optional but must be a valid URI.

Setting Entry Data Points

Here's a summary of the Core API for Entries/Items. You should note it comprises not only the basic RSS and Atom standards, but also accounts for a number of included Extensions bundled with Zend_Feed_Writer. The naming of these Extension sourced methods remain fairly generic - all Extension methods operate at the same level as the Core API though we do allow you to retrieve any specific Extension object separately if required.

Entry Level API Methods
setId() | Set a unique ID associated with this feed. For Atom 1.0 this is an atom:id element, whereas for RSS 2.0 it is added as a guid element. These are optional so long as a link is added, i.e. the link is set as the ID.
setTitle() | Set the title of the feed.
setDescription() | Set the text description of the feed.
setLink() | Set a URI to the HTML website containing the same or similar information as this feed (i.e. if the feed is from a blog, it should provide the blog's URI where the HTML version of the entries can be read).
setFeedLinks() | Add a link to an XML feed, whether the feed being generated or an alternate URI pointing to the same feed but in a different format. At a minimum, it is recommended to include a link to the feed being generated so it has an identifiable final URI allowing a client to track its location changes without necessitating constant redirects. The parameter is an array of arrays, where each sub-array contains the keys "type" and "uri". The type should be one of "atom", "rss", or "rdf". If a type is omitted, it defaults to the type used when rendering the feed.
setAuthors() | Sets the data for authors. The parameter is an array of arrays where each sub-array may contain the keys "name", "email" and "uri". The "uri" value is only applicable for Atom feeds since RSS contains no facility to show it. For RSS 2.0, rendering will create two elements - an author element containing the email reference with the name in brackets, and a Dublin Core creator element only containing the name.
setAuthor() | Sets the data for a single author following the same format as described above for a single sub-array.
setDateCreated() | Sets the date on which this feed was created. Generally only applicable to Atom where it represents the date the resource described by an Atom 1.0 document was created. The expected parameter may be a UNIX timestamp or a Zend_Date object.
getDateModified() | Sets the date on which this feed was last modified. The expected parameter may be a UNIX timestamp or a Zend_Date object.
setLanguage() | Sets the language of the feed. This will be omitted unless set.
getGenerator() | Allows the setting of a generator. The parameter should be an array containing the keys "name", "version" and "uri". If omitted a default generator will be added referencing Zend_Feed_Writer, the current Zend Framework version and the Framework's URI.
setCopyright() | Sets a copyright notice associated with the feed.
setHubs() | Accepts an array of Pubsubhubbub Hub Endpoints to be rendered in the feed as Atom links so that PuSH Subscribers may subscribe to your feed. Note that you must implement a Pubsubhubbub Publisher in order for real-time updates to be enabled. A Publisher may be implemented using Zend_Feed_Pubsubhubbub_Publisher.
setCategories() | Accepts an array of categories for rendering, where each element is itself an array whose possible keys include "term", "label" and "scheme". The "term" is a typically a category name suitable for inclusion in a URI. The "label" may be a human readable category name supporting special characters (it is encoded during rendering) and is a required key. The "scheme" (called the domain in RSS) is optional but must be a valid URI.
Zend_Feed_Reader
Zend_Feed
Zend Framework手册 中文版
Zend_Feed_Pubsubhubbub
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Feed
  • 介绍
  • 导入Feeds
  • 从网页上获得Feed
  • RSS Feed的使用
  • Atom Feed的使用
  • 单个Atom条目的处理
  • 修改Feed和条目结构
  • 自定义Feed和条目类
  • Zend_Feed_Reader
  • Zend_Feed_Writer
  • Zend_Feed_Pubsubhubbub


Zend_Feed_Pubsubhubbub - Zend Framework Manual

Zend_Feed_Writer
Zend_Feed
Zend Framework手册 中文版
Zend_File

Zend_Feed_Pubsubhubbub

Zend_Feed_Pubsubhubbub is an implementation of the PubSubHubbub Core 0.2 Specification (Working Draft). It offers implementations of a Pubsubhubbub Publisher and Subscriber suited to Zend Framework and other PHP applications.

What is Pubsubhubbub?

Pubsubhubbub is an open, simple web-scale pubsub protocol. A common use case to enable blogs (Publishers) to "push" updates from their RSS or Atom feeds (Topics) to end Subscribers. These Subscribers will have subscribed to the blog's RSS or Atom feed via a Hub, a central server which is notified of any updates by the Publisher and which then distributes these updates to all Subscribers. Any feed may advertise that it supports one or more Hubs using an Atom namespaced link element with a rel attribute of "hub".

Pubsubhubbub has garnered attention because it is a pubsub protocol which is easy to implement and which operates over HTTP. Its philosophy is to replace the traditional model where blog feeds have been polled at regular intervals to detect and retrieve updates. Depending on the frequency of polling, this can take a lot of time to propagate updates to interested parties from planet aggregators to desktop readers. With a pubsub system in place, updates are not simply polled by Subscribers, they are pushed to Subscribers, elimenating any delay. For this reason, Pubsubhubbub forms part of what has been dubbed the real-time web.

The protocol does not exist in isolation. Pubsub systems have been around for a while, such as the familiar Jabber Publish-Subscribe protocol, XEP-0060, or the less well known rssCloud (described in 2001). However these have not achieved widespread adoption typically due to either their complexity, poor timing or lack of suitability for web applications. rssCloud, which was recently revived as a response to the appearance of Pubsubhubbub, has also seen its usage increase significantly though it lacks a formal specification and currently does not support Atom 1.0 feeds.

Perhaps surprisingly given its relative early age, Pubsubhubbub is already in use including in Google Reader, Feedburner, and there are plugins available for Wordpress blogs.

Architecture

Zend_Feed_Pubsubhubbub implements two sides of the Pubsubhubbub 0.2 Specification: a Publisher and a Subscriber. It does not currently implement a Hub Server though this is in progress for a future Zend Framework release.

A Publisher is responsible for notifying all supported Hubs (many can be supported to add redundancy to the system) of any updates to its feeds, whether they be Atom or RSS based. This is achieved by pinging the supported Hub Servers with the URL of the updated feed. In Pubsubhubbub terminology, any updatable resource capable of being subscribed to is referred to as a Topic. Once a ping is received, the Hub will request the updated feed, process it for updated items, and forward all updates to all Subscribers subscribed to that feed.

A Subscriber is any party or application which subscribes to one or more Hubs to receive updates from a Topic hosted by a Publisher. The Subscriber never directly communicates with the Publisher since the Hub acts as an intermediary, accepting subscriptions and sending updates to subscribed Subscribers. The Subscriber therefore communicates only with the Hub, either to subscribe/unsubscribe to Topics, or when it receives updates from the Hub. This communication design ("Fat Pings") effectively removes the possibility of a "Thundering Herd" issue. This occurs in a pubsub system where the Hub merely informs Subscribers that an update is available, prompting all Subscribers to immediately retrieve the feed from the Publisher giving rise to a traffic spike. In Pubsubhubbub, the Hub distributes the actual update in a "Fat Ping" so the Publisher is not subjected to any traffic spike.

Zend_Feed_Pubsubhubbub implements Pubsubhubbub Publishers and Subscribers with the classes Zend_Feed_Pubsubhubbub_Publisher and Zend_Feed_Pubsubhubbub_Subscriber. In addition, the Subscriber implementation may handle any feed updates forwarded from a Hub by using Zend_Feed_Pubsubhubbub_Subscriber_Callback. These classes, their use cases, and APIs are covered in subsequent sections.

Zend_Feed_Pubsubhubbub_Publisher

In Pubsubhubbub, the Publisher is the party who publishes a live feed and frequently updates it with new content. This may be a blog, an aggregator, or even a web service with a public feed based API. In order for these updates to be pushed to Subscribers, the Publisher must notify all of its supported Hubs that an update has occured using a simple HTTP POST request containing the URI or the updated Topic (i.e the updated RSS or Atom feed). The Hub will confirm receipt of the notification, fetch the updated feed, and forward any updates to any Subscribers who have subscribed to that Hub for updates from the relevant feed.

By design, this means the Publisher has very little to do except send these Hub pings whenever its feeds change. As a result, the Publisher implementation is extremely simple to use and requires very little work to setup and use when feeds are updated.

Zend_Feed_Pubsubhubbub_Publisher implements a full Pubsubhubbub Publisher. Its setup for use is also simple, requiring mainly that it is configured with the URI endpoint for all Hubs to be notified of updates, and the URIs of all Topics to be included in the notifications.

The following example shows a Publisher notifying a collection of Hubs about updates to a pair of local RSS and Atom feeds. The class retains a collection of errors which include the Hub URLs, so the notification can be re-attempted later and/or logged if any notifications happen to fail. Each resulting error array also includes a "response" key containing the related HTTP response object. In the event of any errors, it is strongly recommended to attempt the operation for failed Hub Endpoints at least once more at a future time. This may require the use of either a scheduled task for this purpose or a job queue though such extra steps are optional.

  1. $publisher = new Zend_Feed_Pubsubhubbub_Publisher;
  2. $publisher->addHubUrls(array(
  3.     'http://pubsubhubbub.appspot.com/',
  4.     'http://hubbub.example.com',
  5. ));
  6. $publisher->addUpdatedTopicUrls(array(
  7.     'http://www.example.net/rss',
  8.     'http://www.example.net/atom',
  9. ));
  10. $publisher->notifyAll();
  11.
  12. if (!$publisher->isSuccess()) {
  13.     // check for errors
  14.     $errors     = $publisher->getErrors();
  15.     $failedHubs = array()
  16.     foreach ($errors as $error) {
  17.         $failedHubs[] = $error['hubUrl'];
  18.     }
  19. }
  20.
  21. // reschedule notifications for the failed Hubs in $failedHubs

If you prefer having more concrete control over the Publisher, the methods addHubUrls() and addUpdatedTopicUrls() pass each array value to the singular addHubUrl() and addUpdatedTopicUrl() public methods. There are also matching removeUpdatedTopicUrl() and removeHubUrl() methods.

You can also skip setting Hub URIs, and notify each in turn using the notifyHub() method which accepts the URI of a Hub endpoint as its only argument.

There are no other tasks to cover. The Publisher implementation is very simple since most of the feed processing and distribution is handled by the selected Hubs. It is however important to detect errors and reschedule notifications as soon as possible (with a reasonable maximum number of retries) to ensure notifications reach all Subscribers. In many cases as a final alternative, Hubs may frequently poll your feeds to offer some additional tolerance for failures both in terms of their own temporary downtime or Publisher errors/downtime.

Zend_Feed_Pubsubhubbub_Subscriber

In Pubsubhubbub, the Subscriber is the party who wishes to receive updates to any Topic (RSS or Atom feed). They achieve this by subscribing to one or more of the Hubs advertised by that Topic, usually as a set of one or more Atom 1.0 links with a rel attribute of "hub". The Hub from that point forward will send an Atom or RSS feed containing all updates to that Subscriber's Callback URL when it receives an update notification from the Publisher. In this way, the Subscriber need never actually visit the original feed (though it's still recommended at some level to ensure updates are retrieved if ever a Hub goes offline). All subscription requests must contain the URI of the Topic being subscribed and a Callback URL which the Hub will use to confirm the subscription and to forward updates.

The Subsciber therefore has two roles. To create and manage subscriptions, including subscribing for new Topics with a Hub, unsubscribing (if necessary), and periodically renewing subscriptions since they may have a limited validity as set by the Hub. This is handled by Zend_Feed_Pubsubhubbub_Subscriber.

The second role is to accept updates sent by a Hub to the Subscriber's Callback URL, i.e. the URI the Subscriber has assigned to handle updates. The Callback URL also handles events where the Hub contacts the Subscriber to confirm all subscriptions and unsubscriptions. This is handled by using an instance of Zend_Feed_Pubsubhubbub_Subscriber_Callback when the Callback URL is accessed.

Important

Zend_Feed_Pubsubhubbub_Subscriber implements the Pubsubhubbub 0.2 Specification. As this is a new specification version not all Hubs currently implement it. The new specification allows the Callback URL to include a query string which is used by this class, but not supported by all Hubs. In the interests of maximising compatibility it is therefore recommended that the query string component of the Subscriber Callback URI be presented as a path element, i.e. recognised as a parameter in the route associated with the Callback URI and used by the application's Router.

Subscribing and Unsubscribing

Zend_Feed_Pubsubhubbub_Subscriber implements a full Pubsubhubbub Subscriber capable of subscribing to, or unsubscribing from, any Topic via any Hub advertised by that Topic. It operates in conjunction with Zend_Feed_Pubsubhubbub_Subscriber_Callback which accepts requests from a Hub to confirm all subscription or unsubscription attempts (to prevent third-party misuse).

Any subscription (or unsubscription) requires the relevant information before proceeding, i.e. the URI of the Topic (Atom or RSS feed) to be subscribed to for updates, and the URI of the endpoint for the Hub which will handle the subscription and forwarding of the updates. The lifetime of a subscription may be determined by the Hub but most Hubs should support automatic subscription refreshes by checking with the Subscriber. This is supported by Zend_Feed_Pubsubhubbub_Subscriber_Callback and requires no other work on your part. It is still strongly recommended that you use the Hub sourced subscription time to live (ttl) to schedule the creation of new subscriptions (the process is identical to that for any new subscription) to refresh it with the Hub. While it should not be necessary per se, it covers cases where a Hub may not support automatic subscription refreshing and rules out Hub errors for additional redundancy.

With the relevant information to hand, a subscription can be attempted as demonstrated below:

  1. $storage = new Zend_Feed_Pubsubhubbub_Model_Subscription;
  2.
  3.     $subscriber = new Zend_Feed_Pubsubhubbub_Subscriber;
  4.     $subscriber->setStorage($storage);
  5.     $subscriber->addHubUrl('http://hubbub.example.com');
  6.     $subscriber->setTopicUrl('http://www.example.net/rss.xml');
  7.     $subscriber->setCallbackUrl('http://www.mydomain.com/hubbub/callback');
  8.     $subscriber->subscribeAll();

In order to store subscriptions and offer access to this data for general use, the component requires a database (a schema is provided later in this section). By default, it is assumed the table name is "subscription" and it utilises Zend_Db_Table_Abstract in the background meaning it will use the default adapter you have set for your application. You may also pass a specific custom Zend_Db_Table_Abstract instance into the associated model Zend_Feed_Pubsubhubbub_Model_Subscription. This custom adapter may be as simple in intent as changing the table name to use or as complex as you deem necessary.

While this Model is offered as a default ready-to-roll solution, you may create your own Model using any other backend or database layer (e.g. Doctrine) so long as the resulting class implements the interface Zend_Feed_Pubsubhubbub_Model_SubscriptionInterface.

An example schema (MySQL) for a subscription table accessible by the provided model may look similar to:

  1. CREATE TABLE IF NOT EXISTS `subscription` (
  2.   `id` varchar(32) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
  3.   `topic_url` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  4.   `hub_url` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  5.   `created_time` datetime DEFAULT NULL,
  6.   `last_modified` datetime DEFAULT NULL,
  7.   `lease_seconds` bigint(20) DEFAULT NULL,
  8.   `verify_token` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  9.   `secret` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  10.   `expiration_time` datetime DEFAULT NULL,
  11.   `subscription_state` varchar(12) COLLATE utf8_unicode_ci DEFAULT NULL,
  12.   PRIMARY KEY (`id`)
  13. ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

Behind the scenes, the Subscriber above will send a request to the Hub endpoint containing the following parameters (based on the previous example):

Subscription request parameters
Parameter Value Explanation
hub.callback http://www.mydomain.com/hubbub/callback?xhub.subscription=5536df06b5dcb966edab3a4c4d56213c16a8184

The URI used by a Hub to contact the Subscriber and either request confirmation of a (un)subscription request or send updates from subscribed feeds. The appended query string contains a custom parameter (hence the xhub designation). It is a query string parameter preserved by the Hub and resent with all Subscriber requests. Its purpose is to allow the Subscriber to identify and look up the subscription associated with any Hub request in a backend storage medium. This is a non-standard parameter used by this component in preference to encoding a subscription key in the URI path which is more difficult to implement in a Zend Framework application.

Nevertheless, since not all Hubs support query string parameters, we still strongly recommend adding the subscription key as a path component in the form http://www.mydomain.com/hubbub/callback/5536df06b5dcb966edab3a4c4d56213c16a8184. To accomplish this, it requires defining a route capable of parsing out the final value of the key and then retrieving the value and passing it to the Subscriber Callback object. The value would be passed into the method Zend_Pubsubhubbub_Subscriber_Callback::setSubscriptionKey(). A detailed example is offered later.

hub.lease_seconds 2592000

The number of seconds for which the Subscriber would like a new subscription to remain valid for (i.e. a TTL). Hubs may enforce their own maximum subscription period. All subscriptions should be renewed by simply re-subscribing before the subscription period ends to ensure continuity of updates. Hubs should additionally attempt to automatically refresh subscriptions before they expire by contacting Subscribers (handled automatically by the Callback class).

hub.mode subscribe

Simple value indicating this is a subscription request. Unsubscription requests would use the "unsubscribe" value.

hub.topic http://www.example.net/rss.xml

The URI of the topic (i.e. Atom or RSS feed) which the Subscriber wishes to subscribe to for updates.

hub.verify sync

Indicates to the Hub the preferred mode of verifying subscriptions or unsubscriptions. It is repeated twice in order of preference. Technically this component does not distinguish between the two modes and treats both equally.

hub.verify async

Indicates to the Hub the preferred mode of verifying subscriptions or unsubscriptions. It is repeated twice in order of preference. Technically this component does not distinguish between the two modes and treats both equally.

hub.verify_token 3065919804abcaa7212ae89.879827871253878386

A verification token returned to the Subscriber by the Hub when it is confirming a subscription or unsubscription. Offers a measure of reliance that the confirmation request originates from the correct Hub to prevent misuse.

You can modify several of these parameters to indicate a different preference. For example, you can set a different lease seconds value using Zend_Pubsubhubbub_Subscriber::setLeaseSeconds() or show a preference for the async verify mode by using setPreferredVerificationMode(Zend_Feed_Pubsubhubbub::VERIFICATION_MODE_ASYNC). However the Hubs retain the capability to enforce their own preferences and for this reason the component is deliberately designed to work across almost any set of options with minimum end-user configuration required. Conventions are great when they work!

Note: While Hubs may require the use of a specific verification mode (both are supported by Zend_Pubsubhubbub), you may indicate a specific preference using the setPreferredVerificationMode() method. In "sync" (synchronous) mode, the Hub attempts to confirm a subscription as soon as it is received, and before responding to the subscription request. In "async" (asynchronous) mode, the Hub will return a response to the subscription request immediately, and its verification request may occur at a later time. Since Zend_Pubsubhubbub implements the Subscriber verification role as a separate callback class and requires the use of a backend storage medium, it actually supports both transparently though in terms of end-user performance, asynchronous verification is very much preferred to eliminate the impact of a poorly performing Hub tying up end-user server resources and connections for too long.

Unsubscribing from a Topic follows the exact same pattern as the previous example, with the exception that we should call unsubscribeAll() instead. The parameters included are identical to a subscription request with the exception that "hub.mode" is set to "unsubscribe".

By default, a new instance of Zend_Pubsubhubbub_Subscriber will attempt to use a database backed storage medium which defaults to using the default Zend_Db adapter with a table name of "subscription". It is recommended to set a custom storage solution where these defaults are not apt either by passing in a new Model supporting the required interface or by passing a new instance of Zend_Db_Table_Abstract to the default Model's constructor to change the used table name.

Handling Subscriber Callbacks

Whenever a subscription or unsubscription request is made, the Hub must verify the request by forwarding a new verification request to the Callback URL set in the subscription/unsubscription parameters. To handle these Hub requests, which will include all future communications containing Topic (feed) updates, the Callback URL should trigger the execution of an instance of Zend_Pubsubhubbub_Subscriber_Callback to handle the request.

The Callback class should be configured to use the same storage medium as the Subscriber class. Using it is quite simple since most of its work is performed internally.

  1. $storage = new Zend_Feed_Pubsubhubbub_Model_Subscription;
  2.     $callback = new Zend_Feed_Pubsubhubbub_Subscriber_Callback;
  3.     $callback->setStorage($storage);
  4.     $callback->handle();
  5.     $callback->sendResponse();
  6.
  7.     /**
  8.      * Check if the callback resulting in the receipt of a feed update.
  9.      * Otherwise it was either a (un)sub verification request or invalid request.
  10.      * Typically we need do nothing other than add feed update handling - the rest
  11.      * is handled internally by the class.
  12.      */
  13.     if ($callback->hasFeedUpdate()) {
  14.         $feedString = $callback->getFeedUpdate();
  15.         /**
  16.          *  Process the feed update asynchronously to avoid a Hub timeout.
  17.          */
  18.     }

Note: It should be noted that Zend_Feed_Pubsubhubbub_Subscriber_Callback may independently parse any incoming query string and other parameters. This is necessary since PHP alters the structure and keys of a query string when it is parsed into the $_GET or $_POST superglobals. For example, all duplicate keys are ignored and periods are converted to underscores. Pubsubhubbub features both of these in the query strings it generates.

Important

It is essential that developers recognise that Hubs are only concerned with sending requests and receiving a response which verifies its receipt. If a feed update is received, it should never be processed on the spot since this leaves the Hub waiting for a response. Rather, any processing should be offloaded to another process or deferred until after a response has been returned to the Hub. One symptom of a failure to promptly complete Hub requests is that a Hub may continue to attempt delivery of the update/verification request leading to duplicated update attempts being processed by the Subscriber. This appears problematic - but in reality a Hub may apply a timeout of just a few seconds, and if no response is received within that time it may disconnect (assuming a delivery failure) and retry later. Note that Hubs are expected to distribute vast volumes of updates so their resources are stretched - please do process feeds asynchronously (e.g. in a separate process or a job queue or even a cron scheduled task) as much as possible.

Setting Up And Using A Callback URL Route

As noted earlier, the Zend_Feed_Pubsubhubbub_Subscriber_Callback class receives the combined key associated with any subscription from the Hub via one of two methods. The technically preferred method is to add this key to the Callback URL employed by the Hub in all future requests using a query string parameter with the key "xhub.subscription". However, for historical reasons, primarily that this was not supported in Pubsubhubbub 0.1 (it was recently added in 0.2 only), it is strongly recommended to use the most compatible means of adding this key to the Callback URL by appending it to the URL's path.

Thus the URL http://www.example.com/callback?xhub.subscription=key would become http://www.example.com/callback/key.

Since the query string method is the default in anticipation of a greater level of future support for the full 0.2 specification, this requires some additional work to implement.

The first step to to make the Zend_Feed_Pubsubhubbub_Subscriber_Callback class aware of the path contained subscription key. It's manually injected therefore since it also requires manually defining a route for this purpose. This is achieved simply by called the method Zend_Feed_Pubsubhubbub_Subscriber_Callback::setSubscriptionKey() with the parameter being the key value available from the Router. The example below demonstrates this using a Zend Framework controller.

  1. class CallbackController extends Zend_Controller_Action
  2. {
  3.
  4.     public function indexAction()
  5.     {
  6.         $storage = new Zend_Feed_Pubsubhubbub_Model_Subscription;
  7.         $callback = new Zend_Feed_Pubsubhubbub_Subscriber_Callback;
  8.         $callback->setStorage($storage);
  9.         /**
  10.          * Inject subscription key parsing from URL path using
  11.          * a parameter from Router.
  12.          */
  13.         $subscriptionKey = $this->_getParam('subkey');
  14.         $callback->setSubscriptionKey($subscriptionKey);
  15.         $callback->handle();
  16.         $callback->sendResponse();
  17.
  18.         /**
  19.          * Check if the callback resulting in the receipt of a feed update.
  20.          * Otherwise it was either a (un)sub verification request or invalid request.
  21.          * Typically we need do nothing other than add feed update handling - the rest
  22.          * is handled internally by the class.
  23.          */
  24.         if ($callback->hasFeedUpdate()) {
  25.             $feedString = $callback->getFeedUpdate();
  26.             /**
  27.              *  Process the feed update asynchronously to avoid a Hub timeout.
  28.              */
  29.         }
  30.     }
  31.
  32. }

Actually adding the route which would map the path-appended key to a parameter for retrieval from a controller can be accomplished using a Route configuration such as the INI formatted example below for use with Zend_Application bootstrapping.

  1. ; Callback Route to enable appending a PuSH Subscription's lookup key
  2. resources.router.routes.callback.route = "callback/:subkey"
  3. resources.router.routes.callback.defaults.module = "default"
  4. resources.router.routes.callback.defaults.controller = "callback"
  5. resources.router.routes.callback.defaults.action = "index"
Zend_Feed_Writer
Zend_Feed
Zend Framework手册 中文版
Zend_File
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Feed
  • 介绍
  • 导入Feeds
  • 从网页上获得Feed
  • RSS Feed的使用
  • Atom Feed的使用
  • 单个Atom条目的处理
  • 修改Feed和条目结构
  • 自定义Feed和条目类
  • Zend_Feed_Reader
  • Zend_Feed_Writer
  • Zend_Feed_Pubsubhubbub


Zend_File - Zend Framework Manual

Zend_Feed_Pubsubhubbub
Zend Framework Reference
Zend Framework手册 中文版
Zend_File_Transfer

Zend_File

Table of Contents
  • Zend_File_Transfer
  • Validators for Zend_File_Transfer
  • Filters for Zend_File_Transfer
Zend_Feed_Pubsubhubbub
Zend Framework Reference
Zend Framework手册 中文版
Zend_File_Transfer
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


Zend_File_Transfer - Zend Framework Manual

Zend_File
Zend_File
Zend Framework手册 中文版
Validators for Zend_File_Transfer

Zend_File_Transfer

Zend_File_Transfer 让开发者控制文件上载和下载。它有用于文件的内置的校验器 并且甚至可以用过滤器来修改文件。Zend_File_Transfer 使用适配器，这样对于 不同的传输协议如 HTTP、 FTP、 WEBDAV 等等就可以使用相同的 API。

Note: 局限
 当前的 Zend_File_Transfer 实现包含在 1.6.0 版中，仅限于 HTTP Post 上载。文件下载和 其它适配器在下次发行时会增加。没实现的功能会抛出异常。所以应该直接使用 Zend_File_Transfer_Adapter_Http 的实例。 当多重适配器可用时，这个就会改变。

Zend_File_Transfer 的用法非常简单。它包括两个部分：用于上载的 HTTP 表单和用 Zend_File_Transfer 来处理上载文件。参见下面的例子：

Example #1 简单的文件上载表单

本例示范了一个基本的文件上传，它使用 Zend_File_Transfer 来完成。 第一部分是文件表单。在例子中，有一个文件要上载。

<form enctype="multipart/form-data" action="/file/upload" method="POST">
    <input type="hidden" name="MAX_FILE_SIZE" value="100000" />
        Choose a file to upload: <input name="uploadedfile" type="file" />
    <br />
    <input type="submit" value="Upload File" />
</form>

注意利用 Zend_Form_Element_File 而不需要手工编写 HTML。

下一步是生成上载的接收者。在本例中接收者是 /file/upload 。所以我们就编写 带有动作 upload 的控制器 file 。

$adapter = new Zend_File_Transfer_Adapter_Http();

$adapter->setDestination('C:\temp');

if (!$adapter->receive()) {
    $messages = $adapter->getMessages();
    echo implode("\n", $messages);
}

正如你所看到的简单的用法，使用 setDestination 定义一个目的地然后调用 receive() 方法。 如果有任何上载错误，就会包含在返回的异常里。

Note: 注意
 记住这只是个最简单的用法，应该 永远不要仅仅把它用于实际的环境， 因为它有严重的安全问题。实际中需要用校验器来增强安全性。

Zend_File
Zend_File
Zend Framework手册 中文版
Validators for Zend_File_Transfer
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_File
  • Zend_File_Transfer
  • Validators for Zend_File_Transfer
  • Filters for Zend_File_Transfer


Validators for Zend_File_Transfer - Zend Framework Manual

Zend_File_Transfer
Zend_File
Zend Framework手册 中文版
Filters for Zend_File_Transfer

Validators for Zend_File_Transfer

Zend_File_Transfer is delivered with several file-related validators which can be used to increase security and prevent possible attacks. Note that these validators are only as effective as how effectively you apply them. All validators provided with Zend_File_Transfer can be found in the Zend_Validator component and are named Zend_Validate_File_*. The following validators are available:

  • Count: This validator checks for the number of files. A minimum and maximum range can be specified. An error will be thrown if either limit is crossed.

  • Crc32: This validator checks for the crc32 hash value of the content from a file. It is based on the Hash validator and provides a convenient and simple validator that only supports Crc32.

  • ExcludeExtension: This validator checks the extension of files. It will throw an error when an given file has a defined extension. With this validator, you can exclude defined extensions from being validated.

  • ExcludeMimeType: This validator validates the MIME type of files. It can also validate MIME types and will throw an error if the MIME type of specified file matches.

  • Exists: This validator checks for the existence of files. It will throw an error when a specified file does not exist.

  • Extension: This validator checks the extension of files. It will throw an error when a specified file has an undefined extension.

  • FilesSize: This validator checks the size of validated files. It remembers internally the size of all checked files and throws an error when the sum of all specified files exceed the defined size. It also provides minimum and maximum values.

  • ImageSize: This validator checks the size of image. It validates the width and height and enforces minimum and maximum dimensions.

  • IsCompressed: This validator checks whether the file is compressed. It is based on the MimeType validator and validates for compression archives like zip or arc. You can also limit it to other archives.

  • IsImage: This validator checks whether the file is an image. It is based on the MimeType validator and validates for image files like jpg or gif. You can also limit it to other image types.

  • Hash: This validator checks the hash value of the content from a file. It supports multiple algorithms.

  • Md5: This validator checks for the md5 hash value of the content from a file. It is based on the Hash validator and provides a convenient and simple validator that only supports Md5.

  • MimeType: This validator validates the MIME type of files. It can also validate MIME types and will throw an error if the MIME type of a specified file does not match.

  • NotExists: This validator checks for the existence of files. It will throw an error when an given file does exist.

  • Sha1: This validator checks for the sha1 hash value of the content from a file. It is based on the Hash validator and provides a convenient and simple validator that only supports sha1.

  • Size: This validator is able to check files for its file size. It provides a minimum and maximum size range and will throw an error when either of these thesholds are crossed.

  • Upload: This validator is internal. It checks if an upload has resulted in an error. You must not set it, as it's automatically set by Zend_File_Transfer itself. So you do not use this validator directly. You should only know that it exists.

  • WordCount: This validator is able to check the number of words within files. It provides a minimum and maximum count and will throw an error when either of these thresholds are crossed.

Using Validators with Zend_File_Transfer

Putting validators to work is quite simple. There are several methods for adding and manipulating validators:

  • isValid($files = null): Checks the specified files using all validators. $files may be either a real filename, the element's name or the name of the temporary file.

  • addValidator($validator, $breakChainOnFailure, $options = null, $files = null): Adds the specified validator to the validator stack (optionally only to the file(s) specified). $validator may be either an actual validator instance or a short name specifying the validator type (e.g., 'Count').

  • addValidators(array $validators, $files = null): Adds the specified validators to the stack of validators. Each entry may be either a validator type/options pair or an array with the key 'validator' specifying the validator. All other options will be considered validator options for instantiation.

  • setValidators(array $validators, $files = null): Overwrites any existing validators with the validators specified. The validators should follow the syntax for addValidators().

  • hasValidator($name): Indicates whether a validator has been registered.

  • getValidator($name): Returns a previously registered validator.

  • getValidators($files = null): Returns registered validators. If $files is specified, returns validators for that particular file or set of files.

  • removeValidator($name): Removes a previously registered validator.

  • clearValidators(): Clears all registered validators.

Example #1 Add Validators to a File Transfer Object

  1. $upload = new Zend_File_Transfer();
  2.
  3. // Set a file size with 20000 bytes
  4. $upload->addValidator('Size', false, 20000);
  5.
  6. // Set a file size with 20 bytes minimum and 20000 bytes maximum
  7. $upload->addValidator('Size', false, array('min' => 20, 'max' => 20000));
  8.
  9. // Set a file size with 20 bytes minimum and 20000 bytes maximum and
  10. // a file count in one step
  11. $upload->setValidators(array(
  12.     'Size'  => array('min' => 20, 'max' => 20000),
  13.     'Count' => array('min' => 1, 'max' => 3),
  14. ));

Example #2 Limit Validators to Single Files

addValidator(), addValidators(), and setValidators() each accept a final $files argument. This argument can be used to specify a particular file or array of files on which to set the given validator.

  1. $upload = new Zend_File_Transfer();
  2.
  3. // Set a file size with 20000 bytes and limits it only to 'file2'
  4. $upload->addValidator('Size', false, 20000, 'file2');

Normally, you should use the addValidators() method, which can be called multiple times.

Example #3 Add Multiple Validators

Often it's simpler just to call addValidator() multiple times with one call for each validator. This also increases readability and makes your code more maintainable. All methods provide a fluent interface, so you can couple the calls as shown below:

  1. $upload = new Zend_File_Transfer();
  2.
  3. // Set a file size with 20000 bytes
  4. $upload->addValidator('Size', false, 20000)
  5.        ->addValidator('Count', false, 2)
  6.        ->addValidator('Filessize', false, 25000);

Note: Note that setting the same validator multiple times is allowed, but doing so can lead to issues when using different options for the same validator.

Last but not least, you can simply check the files using isValid().

Example #4 Validate the Files

isValid() accepts the file name of the uploaded or downloaded file, the temporary file name and or the name of the form element. If no parameter or null is given all files will be validated

  1. $upload = new Zend_File_Transfer();
  2.
  3. // Set a file size with 20000 bytes
  4. $upload->addValidator('Size', false, 20000)
  5.        ->addValidator('Count', false, 2)
  6.        ->addValidator('Filessize', false, 25000);
  7.
  8. if ($upload->isValid()) {
  9.     print "Validation failure";
  10. }

Note: Note that isValid() will be called automatically when you receive the files and have not called it previously.

When validation has failed it is a good idea to get information about the problems found. To get this information, you can use the methods getMessages() which returns all validation messages as array, getErrors() which returns all error codes, and hasErrors() which returns TRUE as soon as a validation error has been found.

Count Validator

The Count validator checks for the number of files which are provided. It supports the following option keys:

  • min: Sets the minimum number of files to transfer.

    Note: When using this option you must give the minimum number of files when calling this validator the first time; otherwise you will get an error in return.

    With this option you can define the minimum number of files you expect to receive.

  • max: Sets the maximum number of files to transfer.

    With this option you can limit the number of files which are accepted but also detect a possible attack when more files are given than defined in your form.

If you initiate this validator with a string or integer, the value will be used as max. Or you can also use the methods setMin() and setMax() to set both options afterwards and getMin() and getMax() to retrieve the actual set values.

Example #5 Using the Count Validator

  1. $upload = new Zend_File_Transfer();
  2.
  3. // Limit the amount of files to maximum 2
  4. $upload->addValidator('Count', false, 2);
  5.
  6. // Limit the amount of files to maximum 5 and minimum 1 file
  7. $upload->addValidator('Count', false, array('min' =>1, 'max' => 5));

Note: Note that this validator stores the number of checked files internally. The file which exceeds the maximum will be returned as error.

Crc32 Validator

The Crc32 validator checks the content of a transferred file by hashing it. This validator uses the hash extension from PHP with the crc32 algorithm. It supports the following options:

  • *: Sets any key or use a numeric array. The values will be used as hash to validate against.

    You can set multiple hashes by using different keys. Each will be checked and the validation will fail only if all values fail.

Example #6 Using the Crc32 Validator

  1. $upload = new Zend_File_Transfer();
  2.
  3. // Checks whether the content of the uploaded file has the given hash
  4. $upload->addValidator('Crc32', false, '3b3652f');
  5.
  6. // Limits this validator to two different hashes
  7. $upload->addValidator('Crc32', false, array('3b3652f', 'e612b69'));

ExcludeExtension Validator

The ExcludeExtension validator checks the file extension of the specified files. It supports the following options:

  • *: Sets any key or use a numeric array. The values will be used to check whether the given file does not use this file extension.

  • case: Sets a boolean indicating whether validation should be case-sensitive. The default is not case sensitive. Note that this key can be applied to for all available extensions.

This validator accepts multiple extensions, either as a comma-delimited string, or as an array. You may also use the methods setExtension(), addExtension(), and getExtension() to set and retrieve extensions.

In some cases it is useful to match in a case-sensitive fashion. So the constructor allows a second parameter called $case which, if set to TRUE, validates the extension by comparing it with the specified values in a case-sensitive fashion.

Example #7 Using the ExcludeExtension Validator

  1. $upload = new Zend_File_Transfer();
  2.
  3. // Do not allow files with extension php or exe
  4. $upload->addValidator('ExcludeExtension', false, 'php,exe');
  5.
  6. // Do not allow files with extension php or exe, but use array notation
  7. $upload->addValidator('ExcludeExtension', false, array('php', 'exe'));
  8.
  9. // Check in a case-sensitive fashion
  10. $upload->addValidator('ExcludeExtension',
  11.                       false,
  12.                       array('php', 'exe', 'case' => true));
  13. $upload->addValidator('ExcludeExtension',
  14.                       false,
  15.                       array('php', 'exe', 'case' => true));

Note: Note that this validator only checks the file extension. It does not check the file's MIME type.

ExcludeMimeType Validator

The ExcludeMimeType validator checks the MIME type of transferred files. It supports the following options:

  • *: Sets any key individually or use a numeric array. Sets the MIME type to validate against.

    With this option you can define the MIME type of files that are not to be accepted.

  • headerCheck: If set to TRUE this option will check the HTTP Information for the file type when the fileInfo or mimeMagic extensions can not be found. The default value for this option is FALSE.

This validator accepts multiple MIME types, either as a comma-delimited string, or as an array. You may also use the methods setMimeType(), addMimeType(), and getMimeType() to set and retrieve the MIME types.

Example #8 Using the ExcludeMimeType Validator

  1. $upload = new Zend_File_Transfer();
  2.
  3. // Does not allow MIME type of gif images for all files
  4. $upload->addValidator('ExcludeMimeType', false, 'image/gif');
  5.
  6. // Does not allow MIME type of gif and jpg images for all given files
  7. $upload->addValidator('ExcludeMimeType', false, array('image/gif',
  8.                                                       'image/jpeg');
  9.
  10. // Does not allow MIME type of the group images for all given files
  11. $upload->addValidator('ExcludeMimeType', false, 'image');

The above example shows that it is also possible to disallow groups of MIME types. For example, to disallow all images, just use 'image' as the MIME type. This can be used for all groups of MIME types like 'image', 'audio', 'video', 'text', etc.

Note: Note that disallowing groups of MIME types will disallow all members of this group even if this is not intentional. When you disallow 'image' you will disallow all types of images like 'image/jpeg' or 'image/vasa'. When you are not sure if you want to disallow all types, you should disallow only specific MIME types instead of complete groups.

Exists Validator

The Exists validator checks for the existence of specified files. It supports the following options:

  • *: Sets any key or use a numeric array to check if the specific file exists in the given directory.

This validator accepts multiple directories, either as a comma-delimited string, or as an array. You may also use the methods setDirectory(), addDirectory(), and getDirectory() to set and retrieve directories.

Example #9 Using the Exists Validator

  1. $upload = new Zend_File_Transfer();
  2.
  3. // Add the temp directory to check for
  4. $upload->addValidator('Exists', false, '\temp');
  5.
  6. // Add two directories using the array notation
  7. $upload->addValidator('Exists',
  8.                       false,
  9.                       array('\home\images', '\home\uploads'));

Note: Note that this validator checks whether the specified file exists in all of the given directories. The validation will fail if the file does not exist in any of the given directories.

Extension Validator

The Extension validator checks the file extension of the specified files. It supports the following options:

  • *: Sets any key or use a numeric array to check whether the specified file has this file extension.

  • case: Sets whether validation should be done in a case-sensitive fashion. The default is no case sensitivity. Note the this key is used for all given extensions.

This validator accepts multiple extensions, either as a comma-delimited string, or as an array. You may also use the methods setExtension(), addExtension(), and getExtension() to set and retrieve extension values.

In some cases it is useful to test in a case-sensitive fashion. Therefore the constructor takes a second parameter $case, which, if set to TRUE, will validate the extension in a case-sensitive fashion.

Example #10 Using the Extension Validator

  1. $upload = new Zend_File_Transfer();
  2.
  3. // Limit the extensions to jpg and png files
  4. $upload->addValidator('Extension', false, 'jpg,png');
  5.
  6. // Limit the extensions to jpg and png files but use array notation
  7. $upload->addValidator('Extension', false, array('jpg', 'png'));
  8.
  9. // Check case sensitive
  10. $upload->addValidator('Extension', false, array('mo', 'png', 'case' => true));
  11. if (!$upload->isValid('C:\temp\myfile.MO')) {
  12.     print 'Not valid because MO and mo do not match with case sensitivity;
  13. }

Note: Note that this validator only checks the file extension. It does not check the file's MIME type.

FilesSize Validator

The FilesSize validator checks for the aggregate size of all transferred files. It supports the following options:

  • min: Sets the minimum aggregate file size. This option defines the minimum aggregate file size to be transferred.

  • max: Sets the maximum aggregate file size.

    This option limits the aggregate file size of all transferred files, but not the file size of individual files.

  • bytestring: Defines whether a failure is to return a user-friendly number or the plain file size.

    This option defines whether the user sees '10864' or '10MB'. The default value is TRUE, so '10MB' is returned if you did not specify otherwise.

You can initialize this validator with a string, which will then be used to set the max option. You can also use the methods setMin() and setMax() to set both options after construction, along with getMin() and getMax() to retrieve the values that have been set previously.

The size itself is also accepted in SI notation as handled by most operating systems. That is, instead of specifying 20000 bytes, 20kB may be given. All file sizes are converted using 1024 as the base value. The following Units are accepted: kB, MB, GB, TB, PB and EB. Note that 1kB is equal to 1024 bytes, 1MB is equal to 1024kB, and so on.

Example #11 Using the FilesSize Validator

  1. $upload = new Zend_File_Transfer();
  2.
  3. // Limit the size of all files to be uploaded to 40000 bytes
  4. $upload->addValidator('FilesSize', false, 40000);
  5.
  6. // Limit the size of all files to be uploaded to maximum 4MB and mimimum 10kB
  7. $upload->addValidator('FilesSize',
  8.                       false,
  9.                       array('min' => '10kB', 'max' => '4MB'));
  10.
  11. // As before, but returns the plain file size instead of a user-friendly string
  12. $upload->addValidator('FilesSize',
  13.                       false,
  14.                       array('min' => '10kB',
  15.                             'max' => '4MB',
  16.                             'bytestring' => false));

Note: Note that this validator internally stores the file size of checked files. The file which exceeds the size will be returned as an error.

ImageSize Validator

The ImageSize validator checks the size of image files. It supports the following options:

  • minheight: Sets the minimum image height.

  • maxheight: Sets the maximum image height.

  • minwidth: Sets the minimum image width.

  • maxwidth: Sets the maximum image width.

The methods setImageMin() and setImageMax() also set both minimum and maximum values, while the methods getMin() and getMax() return the currently set values.

For your convenience there are also the setImageWidth() and setImageHeight() methods, which set the minimum and maximum height and width of the image file. They, too, have corresponding getImageWidth() and getImageHeight() methods to retrieve the currently set values.

To bypass validation of a particular dimension, the relevent option simply should not be set.

Example #12 Using the ImageSize Validator

  1. $upload = new Zend_File_Transfer();
  2.
  3. // Limit the size of a image to a height of 100-200 and a width of
  4. // 40-80 pixel
  5. $upload->addValidator('ImageSize', false,
  6.                       array('minwidth' => 40,
  7.                             'maxwidth' => 80,
  8.                             'minheight' => 100,
  9.                             'maxheight' => 200)
  10.                       );
  11.
  12. // Reset the width for validation
  13. $upload->setImageWidth(array('minwidth' => 20, 'maxwidth' => 200));

IsCompressed Validator

The IsCompressed validator checks if a transferred file is a compressed archive, such as zip or arc. This validator is based on the MimeType validator and supports the same methods and options. You may also limit this validator to particular compression types with the methods described there.

Example #13 Using the IsCompressed Validator

  1. $upload = new Zend_File_Transfer();
  2.
  3. // Checks is the uploaded file is a compressed archive
  4. $upload->addValidator('IsCompressed', false);
  5.
  6. // Limits this validator to zip files only
  7. $upload->addValidator('IsCompressed', false, array('application/zip'));
  8.
  9. // Limits this validator to zip files only using simpler notation
  10. $upload->addValidator('IsCompressed', false, 'zip');

Note: Note that there is no check if you set a MIME type that is not a archive. For example, it would be possible to define gif files to be accepted by this validator. Using the 'MimeType' validator for files which are not archived will result in more readable code.

IsImage Validator

The IsImage validator checks if a transferred file is a image file, such as gif or jpeg. This validator is based on the MimeType validator and supports the same methods and options. You can limit this validator to particular image types with the methods described there.

Example #14 Using the IsImage Validator

  1. $upload = new Zend_File_Transfer();
  2.
  3. // Checks whether the uploaded file is a image file
  4. $upload->addValidator('IsImage', false);
  5.
  6. // Limits this validator to gif files only
  7. $upload->addValidator('IsImage', false, array('application/gif'));
  8.
  9. // Limits this validator to jpeg files only using a simpler notation
  10. $upload->addValidator('IsImage', false, 'jpeg');

Note: Note that there is no check if you set a MIME type that is not an image. For example, it would be possible to define zip files to be accepted by this validator. Using the 'MimeType' validator for files which are not images will result in more readable code.

Hash Validator

The Hash validator checks the content of a transferred file by hashing it. This validator uses the hash extension from PHP. It supports the following options:

  • *: Takes any key or use a numeric array. Sets the hash to validate against.

    You can set multiple hashes by passing them as an array. Each file is checked, and the validation will fail only if all files fail validation.

  • algorithm: Sets the algorithm to use for hashing the content.

    You can set multiple algorithm by calling the addHash() method multiple times.

Example #15 Using the Hash Validator

  1. $upload = new Zend_File_Transfer();
  2.
  3. // Checks if the content of the uploaded file contains the given hash
  4. $upload->addValidator('Hash', false, '3b3652f');
  5.
  6. // Limits this validator to two different hashes
  7. $upload->addValidator('Hash', false, array('3b3652f', 'e612b69'));
  8.
  9. // Sets a different algorithm to check against
  10. $upload->addValidator('Hash',
  11.                       false,
  12.                       array('315b3cd8273d44912a7',
  13.                             'algorithm' => 'md5'));

Note: This validator supports about 34 different hash algorithms. The most common include 'crc32', 'md5' and 'sha1'. A comprehesive list of supports hash algorithms can be found at the » hash_algos method on the » php.net site.

Md5 Validator

The Md5 validator checks the content of a transferred file by hashing it. This validator uses the hash extension for PHP with the md5 algorithm. It supports the following options:

  • *: Takes any key or use a numeric array.

    You can set multiple hashes by passing them as an array. Each file is checked, and the validation will fail only if all files fail validation.

Example #16 Using the Md5 Validator

  1. $upload = new Zend_File_Transfer();
  2.
  3. // Checks if the content of the uploaded file has the given hash
  4. $upload->addValidator('Md5', false, '3b3652f336522365223');
  5.
  6. // Limits this validator to two different hashes
  7. $upload->addValidator('Md5',
  8.                       false,
  9.                       array('3b3652f336522365223',
  10.                             'eb3365f3365ddc65365'));

MimeType Validator

The MimeType validator checks the MIME type of transferred files. It supports the following options:

  • *: Sets any key or use a numeric array. Sets the MIME type to validate against.

    Defines the MIME type of files to be accepted.

  • headerCheck: If set to TRUE this option will check the HTTP Information for the file type when the fileInfo or mimeMagic extensions can not be found. The default value for this option is FALSE.

  • magicfile: The magicfile to be used.

    With this option you can define which magicfile to use. When it's not set or empty, the MAGIC constant will be used instead. This option is available since Zend Framework 1.7.1.

This validator accepts multiple MIME type, either as a comma-delimited string, or as an array. You may also use the methods setMimeType(), addMimeType(), and getMimeType() to set and retrieve MIME type.

You can also set the magicfile which shall be used by fileinfo with the 'magicfile' option. Additionally there are convenient setMagicFile() and getMagicFile() methods which allow later setting and retrieving of the magicfile parameter. This methods are available since Zend Framework 1.7.1.

Example #17 Using the MimeType Validator

  1. $upload = new Zend_File_Transfer();
  2.
  3. // Limit the MIME type of all given files to gif images
  4. $upload->addValidator('MimeType', false, 'image/gif');
  5.
  6. // Limit the MIME type of all given files to gif and jpeg images
  7. $upload->addValidator('MimeType', false, array('image/gif', 'image/jpeg');
  8.
  9. // Limit the MIME type of all given files to the group images
  10. $upload->addValidator('MimeType', false, 'image');
  11.
  12. // Use a different magicfile
  13. $upload->addValidator('MimeType',
  14.                       false,
  15.                       array('image',
  16.                             'magicfile' => '/path/to/magicfile.mgx'));

The above example shows that it is also possible to limit the accepted MIME type to a group of MIME types. To allow all images just use 'image' as MIME type. This can be used for all groups of MIME types like 'image', 'audio', 'video', 'text, and so on.

Note: Note that allowing groups of MIME types will accept all members of this group even if your application does not support them. When you allow 'image' you will also get 'image/xpixmap' or 'image/vasa' which could be problematic. When you are not sure if your application supports all types you should better allow only defined MIME types instead of the complete group.

Note: This component will use the fileinfo extension if it is available. If it's not, it will degrade to the mime_content_type function. And if the function call fails it will use the MIME type which is given by HTTP.
You should be aware of possible security problems when you have whether fileinfo nor mime_content_type available. The MIME type given by HTTP is not secure and can be easily manipulated.

NotExists Validator

The NotExists validator checks for the existence of the provided files. It supports the following options:

  • *: Set any key or use a numeric array. Checks whether the file exists in the given directory.

This validator accepts multiple directories either as a comma-delimited string, or as an array. You may also use the methods setDirectory(), addDirectory(), and getDirectory() to set and retrieve directories.

Example #18 Using the NotExists Validator

  1. $upload = new Zend_File_Transfer();
  2.
  3. // Add the temp directory to check
  4. $upload->addValidator('NotExists', false, '\temp');
  5.
  6. // Add two directories using the array notation
  7. $upload->addValidator('NotExists', false,
  8.                       array('\home\images',
  9.                             '\home\uploads')
  10.                      );

Note: Note that this validator checks if the file does not exist in all of the provided directories. The validation will fail if the file does exist in any of the given directories.

Sha1 Validator

The Sha1 validator checks the content of a transferred file by hashing it. This validator uses the hash extension for PHP with the sha1 algorithm. It supports the following options:

  • *: Takes any key or use a numeric array.

    You can set multiple hashes by passing them as an array. Each file is checked, and the validation will fail only if all files fail validation.

Example #19 Using the sha1 Validator

  1. $upload = new Zend_File_Transfer();
  2.
  3. // Checks if the content of the uploaded file has the given hash
  4. $upload->addValidator('sha1', false, '3b3652f336522365223');
  5.
  6. // Limits this validator to two different hashes
  7. $upload->addValidator('Sha1',
  8.                       false, array('3b3652f336522365223',
  9.                                    'eb3365f3365ddc65365'));

Size Validator

The Size validator checks for the size of a single file. It supports the following options:

  • min: Sets the minimum file size.

  • max: Sets the maximum file size.

  • bytestring: Defines whether a failure is returned with a user-friendly number, or with the plain file size.

    With this option you can define if the user gets '10864' or '10MB'. Default value is TRUE which returns '10MB'.

You can initialize this validator with a string, which will then be used to set the max option. You can also use the methods setMin() and setMax() to set both options after construction, along with getMin() and getMax() to retrieve the values that have been set previously.

The size itself is also accepted in SI notation as handled by most operating systems. That is, instead of specifying 20000 bytes, 20kB may be given. All file sizes are converted using 1024 as the base value. The following Units are accepted: kB, MB, GB, TB, PB and EB. Note that 1kB is equal to 1024 bytes, 1MB is equal to 1024kB, and so on.

Example #20 Using the Size Validator

  1. $upload = new Zend_File_Transfer();
  2.
  3. // Limit the size of a file to 40000 bytes
  4. $upload->addValidator('Size', false, 40000);
  5.
  6. // Limit the size a given file to maximum 4MB and mimimum 10kB
  7. // Also returns the plain number in case of an error
  8. // instead of a user-friendly number
  9. $upload->addValidator('Size',
  10.                       false,
  11.                       array('min' => '10kB',
  12.                             'max' => '4MB',
  13.                             'bytestring' => false));

WordCount Validator

The WordCount validator checks for the number of words within provided files. It supports the following option keys:

  • min: Sets the minimum number of words to be found.

  • max: Sets the maximum number of words to be found.

If you initiate this validator with a string or integer, the value will be used as max. Or you can also use the methods setMin() and setMax() to set both options afterwards and getMin() and getMax() to retrieve the actual set values.

Example #21 Using the WordCount Validator

  1. $upload = new Zend_File_Transfer();
  2.
  3. // Limit the amount of words within files to maximum 2000
  4. $upload->addValidator('WordCount', false, 2000);
  5.
  6. // Limit the amount of words within files to maximum 5000 and minimum 1000 words
  7. $upload->addValidator('WordCount', false, array('min' => 1000, 'max' => 5000));
Zend_File_Transfer
Zend_File
Zend Framework手册 中文版
Filters for Zend_File_Transfer
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_File
  • Zend_File_Transfer
  • Validators for Zend_File_Transfer
  • Filters for Zend_File_Transfer


Filters for Zend_File_Transfer - Zend Framework Manual

Validators for Zend_File_Transfer
Zend_File
Zend Framework手册 中文版
Zend_Filter

Filters for Zend_File_Transfer

Zend_File_Transfer is delivered with several file related filters which can be used to automate several tasks which are often done on files. Note that file filters are applied after validation. Also file filters behave slightly different that other filters. They will always return the file name and not the changed content (which would be a bad idea when working on 1GB files). All filters which are provided with Zend_File_Transfer can be found in the Zend_Filter component and are named Zend_Filter_File_*. The following filters are actually available:

  • Decrypt: This filter can decrypt a encrypted file.

  • Encrypt: This filter can encrypt a file.

  • LowerCase: This filter can lowercase the content of a textfile.

  • Rename: This filter can rename files, change the location and even force overwriting of existing files.

  • UpperCase: This filter can uppercase the content of a textfile.

Using filters with Zend_File_Transfer

The usage of filters is quite simple. There are several methods for adding and manipulating filters.

  • addFilter($filter, $options = null, $files = null): Adds the given filter to the filter stack (optionally only to the file(s) specified). $filter may be either an actual filter instance, or a short name specifying the filter type (e.g., 'Rename').

  • addFilters(array $filters, $files = null): Adds the given filters to the stack of filters. Each entry may be either a filter type/options pair, or an array with the key 'filter' specifying the filter (all other options will be considered filter options for instantiation).

  • setFilters(array $filters, $files = null): Overwrites any existing filters with the filters specified. The filters should follow the syntax for addFilters().

  • hasFilter($name): Indicates if a filter has been registered.

  • getFilter($name): Returns a previously registered filter.

  • getFilters($files = null): Returns registered filters; if $files is passed, returns filters for that particular file or set of files.

  • removeFilter($name): Removes a previously registered filter.

  • clearFilters(): Clears all registered filters.

Example #1 Add filters to a file transfer

  1. $upload = new Zend_File_Transfer();
  2.
  3. // Set a new destination path
  4. $upload->addFilter('Rename', 'C:\picture\uploads');
  5.
  6. // Set a new destination path and overwrites existing files
  7. $upload->addFilter('Rename',
  8.                    array('target' => 'C:\picture\uploads',
  9.                          'overwrite' => true));

Example #2 Limit filters to single files

addFilter(), addFilters(), and setFilters() each accept a final $files argument. This argument can be used to specify a particular file or array of files on which to set the given filter.

  1. $upload = new Zend_File_Transfer();
  2.
  3. // Set a new destination path and limits it only to 'file2'
  4. $upload->addFilter('Rename', 'C:\picture\uploads', 'file2');

Generally you should simply use the addFilters() method, which can be called multiple times.

Example #3 Add multiple filters

Often it's simpler just to call addFilter() multiple times. One call for each filter. This also increases the readability and makes your code more maintainable. As all methods provide a fluent interface you can couple the calls as shown below:

  1. $upload = new Zend_File_Transfer();
  2.
  3. // Set a filesize with 20000 bytes
  4. $upload->addFilter('Rename', 'C:\picture\newjpg', 'file1')
  5.        ->addFilter('Rename', 'C:\picture\newgif', 'file2');

Note: Note that even though setting the same filter multiple times is allowed, doing so can lead to issues when using different options for the same filter.

Decrypt filter

The Decrypt filter allows to decrypt a encrypted file.

This filter makes use of Zend_Filter_Decrypt. It supports the Mcrypt and OpenSSL extensions from PHP. Please read the related section for details about how to set the options for decryption and which options are supported.

This filter supports one additional option which can be used to save the decrypted file with another filename. Set the filename option to change the filename where the decrypted file will be stored. If you suppress this option, the decrypted file will overwrite the original encrypted file.

Example #4 Using the Decrypt filter with Mcrypt

  1. $upload = new Zend_File_Transfer_Adapter_Http();
  2.
  3. // Adds a filter to decrypt the uploaded encrypted file
  4. // with mcrypt and the key mykey
  5. $upload->addFilter('Decrypt',
  6.     array('adapter' => 'mcrypt', 'key' => 'mykey'));

Example #5 Using the Decrypt filter with OpenSSL

  1. $upload = new Zend_File_Transfer_Adapter_Http();
  2.
  3. // Adds a filter to decrypt the uploaded encrypted file
  4. // with openssl and the provided keys
  5. $upload->addFilter('Decrypt',
  6.     array('adapter' => 'openssl',
  7.           'private' => '/path/to/privatekey.pem',
  8.           'envelope' => '/path/to/envelopekey.pem'));

Encrypt filter

The Encrypt filter allows to encrypt a file.

This filter makes use of Zend_Filter_Encrypt. It supports the Mcrypt and OpenSSL extensions from PHP. Please read the related section for details about how to set the options for encryption and which options are supported.

This filter supports one additional option which can be used to save the encrypted file with another filename. Set the filename option to change the filename where the encrypted file will be stored. If you suppress this option, the encrypted file will overwrite the original file.

Example #6 Using the Encrypt filter with Mcrypt

  1. $upload = new Zend_File_Transfer_Adapter_Http();
  2.
  3. // Adds a filter to encrypt the uploaded file
  4. // with mcrypt and the key mykey
  5. $upload->addFilter('Encrypt',
  6.     array('adapter' => 'mcrypt', 'key' => 'mykey'));

Example #7 Using the Encrypt filter with OpenSSL

  1. $upload = new Zend_File_Transfer_Adapter_Http();
  2.
  3. // Adds a filter to encrypt the uploaded file
  4. // with openssl and the provided keys
  5. $upload->addFilter('Encrypt',
  6.     array('adapter' => 'openssl',
  7.           'public' => '/path/to/publickey.pem'));

LowerCase filter

The LowerCase filter allows to change the content of a file to lowercase. You should use this filter only on textfiles.

At initiation you can give a string which will then be used as encoding. Or you can use the setEncoding() method to set it afterwards.

Example #8 Using the LowerCase filter

  1. $upload = new Zend_File_Transfer_Adapter_Http();
  2. $upload->addValidator('MimeType', 'text');
  3.
  4. // Adds a filter to lowercase the uploaded textfile
  5. $upload->addFilter('LowerCase');
  6.
  7. // Adds a filter to lowercase the uploaded file but only for uploadfile1
  8. $upload->addFilter('LowerCase', null, 'uploadfile1');
  9.
  10. // Adds a filter to lowercase with encoding set to ISO-8859-1
  11. $upload->addFilter('LowerCase', 'ISO-8859-1');

Note: Note that due to the fact that the options for the LowerCase filter are optional, you must give a NULL as second parameter (the options) when you want to limit it to a single file element.

Rename filter

The Rename filter allows to change the destination of the upload, the filename and also to overwrite existing files. It supports the following options:

  • source: The name and destination of the old file which shall be renamed.

  • target: The new directory, or filename of the file.

  • overwrite: Sets if the old file overwrites the new one if it already exists. The default value is FALSE.

Additionally you can also use the method setFile() to set files, which erases all previous set, addFile() to add a new file to existing ones, and getFile() to get all actually set files. To simplify things, this filter understands several notations and that methods and constructor understand the same notations.

Example #9 Using the Rename filter

  1. $upload = new Zend_File_Transfer_Adapter_Http();
  2.
  3. // Set a new destination path for all files
  4. $upload->addFilter('Rename', 'C:\mypics\new');
  5.
  6. // Set a new destination path only for uploadfile1
  7. $upload->addFilter('Rename', 'C:\mypics\newgifs', 'uploadfile1');

You can use different notations. Below is a table where you will find a description and the intention for the supported notations. Note that when you use the Adapter or the Form Element you will not be able to use all described notations.

Different notations of the rename filter and their meaning
notation | description
addFile('C:\uploads') | Specifies a new location for all files when the given string is a directory. Note that you will get an exception when the file already exists, see the overwriting parameter.
addFile('C:\uploads\file.ext') | Specifies a new location and filename for all files when the given string is not detected as directory. Note that you will get an exception when the file already exists, see the overwriting parameter.
addFile(array('C:\uploads\file.ext', 'overwrite' => true)) | Specifies a new location and filename for all files when the given string is not detected as directory and overwrites an existing file with the same target name. Note, that you will get no notification that a file was overwritten.
addFile(array('source' => 'C:\temp\uploads', 'target' => 'C:\uploads')) | Specifies a new location for all files in the old location when the given strings are detected as directory. Note that you will get an exception when the file already exists, see the overwriting parameter.
addFile(array('source' => 'C:\temp\uploads', 'target' => 'C:\uploads', 'overwrite' => true)) | Specifies a new location for all files in the old location when the given strings are detected as directory and overwrites and existing file with the same target name. Note, that you will get no notification that a file was overwritten.

UpperCase filter

The UpperCase filter allows to change the content of a file to uppercase. You should use this filter only on textfiles.

At initiation you can give a string which will then be used as encoding. Or you can use the setEncoding() method to set it afterwards.

Example #10 Using the UpperCase filter

  1. $upload = new Zend_File_Transfer_Adapter_Http();
  2. $upload->addValidator('MimeType', 'text');
  3.
  4. // Adds a filter to uppercase the uploaded textfile
  5. $upload->addFilter('UpperCase');
  6.
  7. // Adds a filter to uppercase the uploaded file but only for uploadfile1
  8. $upload->addFilter('UpperCase', null, 'uploadfile1');
  9.
  10. // Adds a filter to uppercase with encoding set to ISO-8859-1
  11. $upload->addFilter('UpperCase', 'ISO-8859-1');

Note: Note that due to the fact that the options for the UpperCase filter are optional, you must give a NULL as second parameter (the options) when you want to limit it to a single file element.

Validators for Zend_File_Transfer
Zend_File
Zend Framework手册 中文版
Zend_Filter
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_File
  • Zend_File_Transfer
  • Validators for Zend_File_Transfer
  • Filters for Zend_File_Transfer


Zend_Filter - Zend Framework Manual

Filters for Zend_File_Transfer
Zend Framework Reference
Zend Framework手册 中文版
简介

Zend_Filter

Table of Contents
  • 简介
  • 标准过滤器类
  • 过滤器链
  • 编写过滤器
  • Zend_Filter_Input
  • Zend_Filter_Inflector
Filters for Zend_File_Transfer
Zend Framework Reference
Zend Framework手册 中文版
简介
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


简介 - Zend Framework Manual

Zend_Filter
Zend_Filter
Zend Framework手册 中文版
标准过滤器类

简介

Zend_Filter 组件提供了一系列普遍使用的数据过滤器(data filter)，同时也提供了一个简单的过滤器链机制，使多个过滤器以用户定义的顺序对一个单一的数据进行过滤。

什么是过滤器(filter)？

在现实世界中，过滤器被用来过滤掉输入物中不需要的部分，并期望产出部分输出物（比如，咖啡）。在这样的情景下，过滤器就像是一个操作员，生产出输入物的子集。这种类型的过滤对Web应用程序来说是很有用的－移除非法的输入数据，去除不必要的空格，等等。

这个过滤器基本的定义，可延伸出包括一般化的输入数据的转化。HTML 实体的转义，是Web应用程序中一个普遍的转化。例如，一个表单字段的值附带着不受信任的数据（比如，来自web浏览器的数据），为了防止不期望的行为发生和安全漏洞，这个值应该不包括 HTML 实体，或只包含已转义的 HTML 实体。为了满足这个需求，输入数据中的 HTML 实体被移除或被转义，当然，这得视具体情况而定。过滤器的第一种定义中就涵盖了过滤器移除 HTML 实体的意思－操作员生产出输入数据的一个子集。然而，过滤器也可转义 HTML 实体，转化输入数据（比如，"&" 被转义成 "&amp;"）。为 Web 开发者支持这样的用例是非常重要的，且在使用Zend_Filter的上下文中，”to filter”的意思是对输入数据执行一些转化。

过滤器的基本用法

确立了这样的过滤器定义，为 Zend_Filter_Interface 接口奠定了理论基础，需要过滤器类实现一个名为 filter() 的方法。

下面一个简单的例子，示范了在2个输入数据上使用过滤器，"&" 符号和双引号 (") 字符：

$htmlEntities = new Zend_Filter_HtmlEntities();

echo $htmlEntities->filter('&'); // &amp;
echo $htmlEntities->filter('"'); // &quot;

使用静态 get() 方法

如果不方便加载给定的过滤器类和创建过滤器的实例，可以使用静态方法 Zend_Filter::get() 作为备用的调用风格。这个方法的第一个参数是数据输入值，将传递给 filter() 方法，第二个参数是个字符串，对应于过滤器类的基本名，和 Zend_Filter 名称空间有关。get() 方法自动加载这个类，创建一个实例，并应用 filter() 方法给数据输入。

echo Zend_Filter::get('&', 'HtmlEntities');

如果过滤器类需要，也可以传递一个数组构造参数

echo Zend_Filter::get('"', 'HtmlEntities', array(ENT_QUOTES));

静态用法对调用过滤器特别方便，但如果对多个输入运行过滤器，按上面第一个例子做更有效，创建一个过滤器对象的实例并调用它的 filter() 方法。

并且，Zend_Filter_Input 类允许初始化和运行多重过滤器，按需的校验器类来处理输入数据，参见 Zend_Filter_Input。

Zend_Filter
Zend_Filter
Zend Framework手册 中文版
标准过滤器类
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Filter
  • 简介
  • 标准过滤器类
  • 过滤器链
  • 编写过滤器
  • Zend_Filter_Input
  • Zend_Filter_Inflector


标准过滤器类 - Zend Framework Manual

简介
Zend_Filter
Zend Framework手册 中文版
过滤器链

标准过滤器类

Zend Framework 带有一组标准的过滤器。

Alnum

返回只保留字母和数字的字符串 $value，这个过滤器包括一个允许空白字符的选项。

Alpha

返回只保留字母的字符串 $value，这个过滤器包括一个允许空白字符的选项。

BaseName

给定包含一个文件的路径字符串，这个过路器将返回这个文件的基本名（base name）。

Digits

返回只保留数字的字符串 $value。

Dir

返回路径的名字部分。

HtmlEntities

返回转换成它们对应 HTML 实体的字符串 $value。

Int

返回整数 $value。

StripNewlines

返回不带任何新行控制符的字符串 $value 。

RealPath

扩展所有符号的链接和解析指向在输入路径里的 '/./', '/../' 和额外的 '/' 字符并且返回规范化后的绝对路径名，返回的结果路径将没有符号链接 '/./' 或 '/../' 部分。

如果失败，例如文件不存在，Zend_Filter_RealPath 将返回 FALSE。在 BSD 系统，如果只有路径最后部分不存在， Zend_Filter_RealPath 不会失败，但其它系统返回 FALSE。

StringToLower

返回按需转换字母成小写的字符串 $value。

StringToUpper

返回按需转换字母成大写的字符串 $value。

StringTrim

返回从头到尾整理过的字符串 $value。

StripTags

返回把 HTML 和 PHP 标签已剥离的（声明为允许的标签不会剥离）输入的字符串。除了能指定允许哪个标签，开发者也可以在所有允许的标签（或只对特定的标签）中指定哪个属性被允许。最后，这个过滤器提供控制是否注释（如 <!-- ... -->）被删除或允许。

简介
Zend_Filter
Zend Framework手册 中文版
过滤器链
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Filter
  • 简介
  • 标准过滤器类
  • 过滤器链
  • 编写过滤器
  • Zend_Filter_Input
  • Zend_Filter_Inflector


过滤器链 - Zend Framework Manual

标准过滤器类
Zend_Filter
Zend Framework手册 中文版
编写过滤器

过滤器链

通常，多个过滤器可以以一个特定的顺序应用到某个值上。例如，登录表单的用户名，应为英文字符且小写。Zend_Filter提供了一个简单的方法，使过滤器可以链接在一起。下面的代码描述了怎样把2个过滤器链接起来且应用到提交上来的用户名值上：

// Create a filter chain and add filters to the chain
$filterChain = new Zend_Filter();
$filterChain->addFilter(new Zend_Filter_Alpha())
            ->addFilter(new Zend_Filter_StringToLower());

// Filter the username
$username = $filterChain->filter($_POST['username']);
过滤器按照他们被添加到Zend_Filter中去的顺序依次执行。上面的例子中，用户名首先被移除任何非英文字母的字符，然后将所有大写字符转化为小写字符。

任何实现了Zend_Filter_Interface接口的，都可被添加到过滤器链中。

标准过滤器类
Zend_Filter
Zend Framework手册 中文版
编写过滤器
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Filter
  • 简介
  • 标准过滤器类
  • 过滤器链
  • 编写过滤器
  • Zend_Filter_Input
  • Zend_Filter_Inflector


Zend_Filter_Inflector - Zend Framework Manual

Zend_Filter_Input
Zend_Filter
Zend Framework手册 中文版
Zend_Form

Zend_Filter_Inflector

Zend_Filter_Inflector 是一个为基于规则的把字符串变形到给定目标的一般意义上的工具。

例如，你可能发现你需要把混合大小写字（MixedCase）或驼峰字符（ camelCasedWords） 变成路径，对于可读性，OS 策略或其它原因， 你也需要把它变成小写，并且你想用短横线（'-'）来隔离单词。变形器（inflector）可以帮你做这些。

Zend_Filter_Inflector 实现 Zend_Filter_Interface， 你可以通过在对象实例中调用 filter() 来执行变形。

Example #1 把混合大小写字（MixedCase）和驼峰字符 （camelCaseText） 变成其它格式

<?php
$inflector = new Zend_Filter_Inflector('pages/:page.:suffix');
$inflector->setRules(array(
    ':page'  => array('Word_CamelCaseToDash', 'StringToLower'),
    'suffix' => 'html'
));

$string   = 'camelCasedWords';
$filtered = $inflector->filter(array('page' => $string)); // pages/camel-cased-words.html

$string   = 'this_is_not_camel_cased';
$filtered = $inflector->filter(array('page' => $string)); // pages/this_is_not_camel_cased.html
?>

操作

变形器要求 target 和一个或多个 rules。 目标基本上是个字符串，它为你想替换的变量定义了占位符。 这些由带有':'的前缀来指定：:script。

当调用 filter() 时，传递一个和在目标中的变量相应的键/值对的数组。

在目标中的每个变量可以有零到多个规则。规则可以是 静态的 或指向 Zend_Filter 类的引用。 静态规则将用提供的文本替换，否则，和提供的规则匹配的类将用于变形这个文本。 类一般使用指示从任何普通前缀剥离的滤器名的短名来指定。

例如，你可以使用 Zend_Filter 的任何具体实现，然而，不用引用它们为 'Zend_Filter_Alpha' 或 'Zend_Filter_StringToLower'， 而是只指定 'Alpha' 或 'StringToLower'。

设置到预备的过滤器的路径

Zend_Filter_Inflector 使用 Zend_Loader_PluginLoader 来管理加载和变形一起使用的过滤器。 缺省地，任何带有 Zend_Filter 前缀的过滤器都可用。 为了访问带有那个前缀的过滤器，但发生在较深的等级结构里，如各种字过滤器，只需要剥离 Zend_Filter 前缀：

<?php
// use Zend_Filter_Word_CamelCaseToDash as a rule
$inflector->addRules(array('script' => 'Word_CamelCaseToDash'));
?>

要设置备用的路径，Zend_Filter_Inflector 有个实用方法 addFilterPrefixPath() 来代理插件加载器：

<?php
$inflector->addFilterPrefixPath('My_Filter', 'My/Filter/');
?>

另外，你可以从变形器获取插件加载器并和它直接互动：

<?php
$loader = $inflector->getPluginLoader();
$loader->addPrefixPath('My_Filter', 'My/Filter/');
?>

更多关于修改过滤器路径的选项，请参考 插件加载器文档 。

设置变形器目标

变形器目标是一个带有一些变量的占位符的字符串。 占位符表现为识别器的形式，缺省为冒号（':'），紧跟着变量名：':script'、 ':path'等。 filter() 方法寻找跟随着被替换的变量名的识别器。

可用使用 setTargetReplacementIdentifier() 方法来改变识别器，或把它当作第三个参数传递给构造器：

<?php
// Via constructor:
$inflector = new Zend_Filter_Inflector('#foo/#bar.#sfx', null, '#');

// Via accessor:
$inflector->setTargetReplacementIdentifier('#');
?>

一般地，通过构造器来设置目标。然而，你想在稍后重置目标（例如，在核心部件里修改缺省变形器，如 ViewRenderer 或 Zend_Layout ）， 可使用 setTarget() ：

<?php
$inflector = $layout->getInflector();
$inflector->setTarget('layouts/:script.phtml');
?>

另外，你可能希望在你的类中有类成员，类用来保持变形器目标是最新的 － 不需要每次直接更新目标 （这样节省调用方法）。setTargetReference() 让你来做这个：

<?php
class Foo
{
    /**
     * @var string Inflector target
     */
    protected $_target = 'foo/:bar/:baz.:suffix';

    /**
     * Constructor
     * @return void
     */
    public function __construct()
    {
        $this->_inflector = new Zend_Filter_Inflector();
        $this->_inflector->setTargetReference($this->_target);
    }

    /**
     * Set target; updates target in inflector
     *
     * @param  string $target
     * @return Foo
     */
    public function setTarget($target)
    {
        $this->_target = $target;
        return $this;
    }
}
?>

变形规则

如在简介中所提到的，有两种类型的规则：静态的和基于过滤器的。

Note: 不论你添加规则给变形器的方法是一个接着一个还是一下子全部，顺序很重要。 更具体的名字或可能包含其它规则名的名字必需在最不具体名之前添加。 例如，假定令各规则名 'moduleDir' 和 'module'，'moduleDir' 规则应当在 'module' 之前出现， 因为 'module' 包含在 'moduleDir' 中，如果 'module' 在 'moduleDir' 之前添加， 'module' 将匹配 'moduleDir' 的一部分并且处理它把 'Dir' 留在在未变形的目标里。

静态规则

静态规则做简单的字符替换，当在静态目标里有片段，但你想让开发者修改的时候使用它们。 使用 setStaticRule() 方法来设置或修改规则：

<?php
$inflector = new Zend_Filter_Inflector(':script.:suffix');
$inflector->setStaticRule('suffix', 'phtml');

// change it later:
$inflector->setStaticRule('suffix', 'php');
?>

很像目标自己，你也可以绑定静态规则到一个引用，让你来更新单个变量而不是请求一个方法调用。 当你的类在内部使用变形器，并且你不想让用户为更新而抓取变形器，这通常很有用， setStaticRuleReference() 方法用来完成这个：

<?php
class Foo
{
    /**
     * @var string Suffix
     */
    protected $_suffix = 'phtml';

    /**
     * Constructor
     * @return void
     */
    public function __construct()
    {
        $this->_inflector = new Zend_Filter_Inflector(':script.:suffix');
        $this->_inflector->setStaticRuleReference('suffix', $this->_suffix);
    }

    /**
     * Set suffix; updates suffix static rule in inflector
     *
     * @param  string $suffix
     * @return Foo
     */
    public function setSuffix($suffix)
    {
        $this->_suffix = $suffix;
        return $this;
    }
}
?>

过滤变形器规则

Zend_Filter 过滤器也可以当作变形器来使用。像静态规则的一方面是可以绑定到目标变量； 不像静态规则一方面是当变形时你可以定义多重过滤器来用。 这些过滤器按顺序来处理，所以小心地按顺序来注册它们，这样对你接收到的数据有意义。

规则可以用 setFilterRule() 它重写任何以前这个变量的规则）或 addFilterRule() （它在已存在的变量的规则上追加新规则）来添加。 过滤器用下列方法之一来指定：

  • String. 字符串可以是过滤器的类名，或者一个类名段去掉任何 在变形器的插件加载器里的前缀（缺省地，去掉 'Zend_Filter' 前缀）。

  • Filter object. 任何实现 Zend_Filter_Interface 的对象实例可当作过滤器来传递。

  • Array. 如上所定义的一个或多个字符串或过滤器对象数组。

<?php
$inflector = new Zend_Filter_Inflector(':script.:suffix');

// Set rule to use Zend_Filter_Word_CamelCaseToDash filter
$inflector->setFilterRule('script', 'Word_CamelCaseToDash');

// Add rule to lowercase string
$inflector->addFilterRule('script', new Zend_Filter_StringToLower());

// Set rules en-masse
$inflector->setFilterRule('script', array(
    'Word_CamelCaseToDash',
    new Zend_Filter_StringToLower()
));
?>

一次设置多个规则

一般地，一次设置多个规则比每次配置一个单个的变量和它的变形器规则要容易。 Zend_Filter_Inflector 的 addRules() 和 setRules() 方法允许这样做。

每个方法带有一个变量/规则对的数组，这里规则是接受的任何规则（字符串、过滤器对象或数组）。 变量名接受一个特殊的符号来允许设置静态规则和过滤器规则，符号有：

  • ':' 前缀 : 过滤器规则。

  • 没有前缀 : 静态规则。

Example #2 一次设置多重规则

<?php
// Could also use setRules() with this notation:
$inflector->addRules(array(
    // filter rules:
    ':controller' => array('CamelCaseToUnderscore','StringToLower'),
    ':action'     => array('CamelCaseToUnderscore','StringToLower'),

    // Static rule:
    'suffix'      => 'phtml'
));
?>

实用方法

Zend_Filter_Inflector 有很多实用方法用来读取和设置插件加载器、处理和读取规则以及当有异常抛出时的控制。

  • 当你配置了自己的插件加载器并希望它和 Zend_Filter_Inflector一起使用， 可以使用 setPluginLoader()； getPluginLoader() 读取当前设置的一个。

  • 当给定的替换识别器传递给它，并在目标中找不到，setThrowTargetExceptionsOn() 可以用来控制 filter() 是否抛出一个异常。 缺省是没有异常抛出。isThrowTargetExceptionsOn() 将告诉你当前值是什么。

  • getRules($spec = null) 可用来读取所有注册的变量规则，或者仅仅是一个单个变量的规则。

  • getRule($spec, $index) 根据给定的变量读取一个单个的规则； 对于有过滤器链的变量读取特定的过滤器规则，这很有用。 必需传递 $index。

  • clearRules() 将清除所有当前注册的规则。

对 Zend_Filter_Inflector 使用 Zend_Config

你可以通过传递 Zend_Config 对象给构造器或setConfig()来使用 Zend_Config 设置规则、过滤器前缀路径和其它在你的变形器里的对象。 可以指定下列设置：

  • target 指定变形目标。

  • filterPrefixPath 指定一个或多个过滤器前缀/路径对给变形器的使用。

  • throwTargetExceptionsOn 是个布尔值，指示当替换识别器在变形后仍存在的时候是否抛出异常。

  • targetReplacementIdentifier 当在目标字符串里识别替换变量时，指定字符来使用。

  • rules 指定变形器规则数组；它应当包含指定值或值的数组的键，和 addRules() 一致。

Example #3 使用 Zend_Config with Zend_Filter_Inflector

<?php
// With the constructor:
$config    = new Zend_Config($options);
$inflector = new Zend_Filter_Inflector($config);

// Or with setConfig():
$inflector = new Zend_Filter_Inflector();
$inflector->setConfig($config);
?>
Zend_Filter_Input
Zend_Filter
Zend Framework手册 中文版
Zend_Form
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Filter
  • 简介
  • 标准过滤器类
  • 过滤器链
  • 编写过滤器
  • Zend_Filter_Input
  • Zend_Filter_Inflector


Zend_Filter_Input - Zend Framework Manual

编写过滤器
Zend_Filter
Zend Framework手册 中文版
Zend_Filter_Inflector

Zend_Filter_Input

Zend_Filter_Input 提供了一个声明接口来联合多重过滤器和校验器，使用 它们来收集数据并在用过滤器和校验器处理之后来获取输入值。为 HTML 输出 安区起见，缺省的返回值是转义格式。

形象地说，这个类是一个外部数据的笼子。数据从外部资源输入到程序，如 HTTP 请求参数、HTTP 头、web 服务或者甚至从数据库或其它文件读取的数据。 首先把数据放入笼子，随后程序只可以通过告诉笼子数据应该是什么样子和如何 使用它来访问数据。笼子检验数据的合法性。对于适当的上下文，可能使用 转义数据。在全部符合这些条件时，笼子才释放数据。用一个简单方便的接口， 它鼓励好的变成习惯并使开发者仔细考虑如何使用数据。

  • Filters 通过删除或修改字符来 转换输入值，目标是 “规格化” 输入值一直到它们符合期望的格式。例如： 如果需要数字字符串，而输入值是 “abc123” ，那么它就被合理地转换成 “123”.

  • Validators 根据条件来检查输入值并报告输入值是否通过测试。 它不修改输入值，但检查可能会失败。例如：如果需要一个 email 地址字符串，而输入值是 “abc123” ，那么这个值就无效。

  • Escapers 通过去除特定字符的魔术行为（magic behavior）来转换一个值。 在一些输出山下文中，特殊字符是有它的意义的。例如：字符 '<' 和 '>' 界定 HTML 标签，如果包含这些字符 的字符串输出到 HTML 上下文，在它们之间的文本可能影响 HTML 的输出和功能。转义字符除掉了特殊意义，所以它们 的输出就是文字输出了。

为使用 Zend_Filter_Input，执行下列步骤：

  1. 声明过滤器和校验器规则

  2. 创建过滤器和校验器的处理器

  3. 提供输入数据

  4. 获取被校验的字段和其它报告

下面一节描述使用这个类的步骤。

声明过滤器和校验器规则

在创建 Zend_Filter_Input 实例之前，声明过滤器规则数组和校验器规则数组。 这个关联数组映射规则名到过滤器或校验器，或者过滤器或校验器链。

在下面的例子中，过滤器规则设置声明 'month' 字段由 Zend_Filter_Digits 来过滤，'account' 字段由 Zend_Filter_StringTrim 来过滤。校验器规则设置 声明只有如果 'account' 字段只包含字母字符时有效。

<?php
$filters = array(
    'month'   => 'Digits',
    'account' => 'StringTrim'
);

$validators = array(
    'account' => 'Alpha'
);

在上述 $filters 数组中的每个键是应用过滤器到特定数据字段的规则的名称。 缺省地，规则的名称也是使用改规则的输入数据字段的名称。

可以用若干格式来声明一个规则：

  • 一个单个的字符串标量（scalar），它映射到一个类名。

    <?php
$validators = array(
    'month'   => 'Digits',
);

  • 实现 Zend_Filter_Interface 或 Zend_Validate_Interface 的类的一个对象实例。

    <?php
$digits = new Zend_Validate_Digits();

$validators = array(
    'month'   => $digits
);

  • 一个数组，声明一个过滤器或者校验器链。这个数组的元素可以是 映射到类名或过滤器/校验器对象的字符串，就像上述例子一样。 另外，可以使用第三种选择：包含映射到带有传递给自己的构造器 的类名的字符串的数组。

    <?php
$validators = array(
    'month'   => array(
        'Digits',                // string
        new Zend_Validate_Int(), // object instance
        array('Between', 1, 12)  // string with constructor arguments
    )
);

Note: 如果用在数组种带有构造器参数来声明过滤器或校验器， 即使这个规则只有一个过滤器或校验器，你也必需做一个规则数组。

你可以在过滤器数组或校验器数组里使用特殊的“通配符”规则键'*'。 意思是在这个规则中声明的过滤器或校验器将应用于所有输入数据域。 注意在过滤器数组或校验器数组里的条目的顺序意义重大，规则使用和你声明时的相同顺序。

<?php
$filters = array(
    '*'     => 'StringTrim',
    'month' => 'Digits'
);

生成过滤器和校验器的处理器

在声明过滤器或校验器数组后，把它们用作 Zend_Filter_Input 的构造器的参数。 它返回一个知道所有过滤和校验规则的对象，你可以用这个对象来处理一组或多组输入数据。

<?php
$input = new Zend_Filter_Input($filters, $validators);

你可以指定输入数据为第三个构造器参数。数据结构是个关联数组。 键是字段名，值是数据值。在 PHP 中标准的 $_GET 和 $_POST 全局变量是该格式的例子。 你可以使用这些变量的一个作为 Zend_Filter_Input 的输入数据。

<?php
$data = $_GET;

$input = new Zend_Filter_Input($filters, $validators, $data);

另外，使用 setData() 方法，用和上述相同的格式传递一个键/值对的关联数组。

<?php
$input = new Zend_Filter_Input($filters, $validators);
$input->setData($newData);

setData() 方法在一个已存在的 Zend_Filter_Input 对象中 在不改变过滤和校验规则下重定义数据。使用该方法，你可以对不同的数据集 运行相同的规则。

获取校验过的字段和其它报告

在声明过滤器和校验器与创建输入处理器之后，你可以获取丢失的、未知的和无效字段的报告。 你也可以在应用过滤器之后获得字段的值。

输入值有效的查询

如果所有输入数据通过校验，isValid() 方法返回 true。 如果有任何字段无效或者任何要求的字段不存在，则返回 false。

<?php
if ($input->isValid()) {
  echo "OK\n";
}

该方法接受一个可选的字符串参数，即一个独立字段。如果指定的字段 通过校验并为读取准备好，isValid('fieldName') 返回 true。

<?php
if ($input->isValid('month')) {
  echo "Field 'month' is OK\n";
}

获得无效、丢失或未知的字段

  • Invalid 是不能通过一个或多个校验检查的字段。

  • Missing 是那些不存在于输入数据，但用 metacommand 'presence'=>'required'（参见在 metacommands 中 后面的章节 ）声明过的字段。

  • Unknown 是那些没有在任何校验器数组中的规则声明的，但出现在输入数据中的字段。

<?php
if ($input->hasInvalid() || $input->hasMissing()) {
  $messages = $input->getMessages();
}

// getMessages() simply returns the merge of getInvalid() and getMissing()

if ($input->hasInvalid()) {
  $invalidFields = $input->getInvalid();
}

if ($input->hasMissing()) {
  $missingFields = $input->getMissing();
}

if ($input->hasUnknown()) {
  $unknownFields = $input->getUnknown();
}

getMessages() 方法的结果是一个关联数组，映射规则名到一个和该规则相关的错误消息的数组。 注意该数组的索引是用在规则声明的规则名，它可能和由该规则检查的字段名不同。

getMessages() 方法返回由 getInvalid() 和 getMissing() 的返回的数组的合并。 这些方法返回消息的子集，和校验失败相关，或者必需声明的字段没有输入。

The getErrors() 方法返回一个关联数组，映射规则名到错误识别器的数组。 错误识别器是规定字符串，用来识别校验错误的原因，消息可以定制。 参见 校验器的基本用法 有更多信息。

你可以指定使用 'missingMessage' 选项的 getMissing() 返回的消息作为 Zend_Filter_Input 构造器的参数或者使用 setOptions() 方法。

<?php
$options = array(
    'missingMessage' => "Field '%field%' is required"
);

$input = new Zend_Filter_Input($filters, $validators, $data, $options);

// alternative method:

$input = new Zend_Filter_Input($filters, $validators, $data);
$input->setOptions($options);

getUnknown() 方法的结果是一个关联数组，映射字段名到字段值。 在这个例子中，字段名（而不是规则名）用作数组键，因为不涉及规则的字段被当作未知字段。

获得有效字段

所有不是无效的、丢失的、未知的字段都是有效的（好像废话一样 Jason Qi）。 你可以用魔术访问器来获得有效字段的值。也有非魔术访问器方法 getEscaped() 和 getUnescaped()。

<?php
$m = $input->month;                 // escaped output from magic accessor
$m = $input->getEscaped('month');   // escaped output
$m = $input->getUnescaped('month'); // not escaped

缺省地，当读取一个值时，用 Zend_Filter_HtmlEntities 来过滤。 因为它是在 HTML 中输出字段值的最普通的用法，所以它是缺省的。 HtmlEntities 过滤器有助于防止无意识的、可能会导致安全问题的代码输出。

Note: 正如上所述，你可以使用 getUnescaped() 方法读取非转义的值， 但必需安全地使用这些值，避免安全问题如被跨站脚本攻击的弱点。

你可以通过在构造器选项数组里指定转义值来为它指定一个不同的过滤器：

<?php
$options = array('escapeFilter' => 'StringTrim');
$input = new Zend_Filter_Input($filters, $validators, $data, $options);

另外，你也可以使用 setDefaultEscapeFilter() 方法：

<?php
$input = new Zend_Filter_Input($filters, $validators, $data);
$input->setDefaultEscapeFilter(new Zend_Filter_StringTrim());

对于任何一种用法，你可以指定转义过滤器作为过滤器类的字符串基础名 或者过滤器类的对象实例。转义过滤器可以是过滤器链的实例、Zend_Filter 类的对象。

转义输出的过滤器应当确保在校验之后运行，其它在过滤器规则的数组中声明的过滤器在数据校验之前应用。 如果转义过滤器在校验之前运行，校验的处理将会很复杂，也将很难提供转义的和非转义的数据版本。 建议使用 setDefaultEscapeFilter() 来声明转义输出的过滤器，而不是在 $filters 数组中。

只有一个方法 getEscaped()，所以你只可以为转义（尽管这个过滤器可以是个过滤器链）指定一个过滤器。 如果需要一个单个的 Zend_Filter_Input 实例来返回使用超过一个过滤器方法的转义输出，你应该继承 Zend_Filter_Input 并在你的子类里实现新方法来用不同的方法获取数值。

使用 Metacommands 来控制过滤器或校验器规则

除了声明从字段到过滤器或校验器的映射，你可以在数组声明中指定一些 "metacommands" ，开控制一些 Zend_Filter_Input 的可选的行为。 Metacommands 在给定的过滤器或校验器数组值里以字符串索引条目的形式出现。

The FIELDS metacommand

如果过滤器或校验器的规则名和需要应用规则的字段名不同，可以用 'fields' metacommand 来指定字段名。

可以用类常量 Zend_Filter_Input::FIELDS 而不是字符串来指定这个 metacommand。

<?php
$filters = array(
    'month' => array(
        'Digits',        // filter name at integer index [0]
        'fields' => 'mo' // field name at string index ['fields']
    )
);

在上例中，过滤器规则使用 'digits' 过滤器给名为 'mo' 的输入字段。 字符串 'month' 变成这个过滤规则的助记键，如果用 'fields' metacommand 指定字段，它不能用做字段名，但可用作规则名。

'fields' metacommand 的缺省值是当前规则的索引。在上例中，如果 'fields' metacommand 没有被指定，规则就应用于名为 'month' 的输入字段。

'fields' metacommand 的另一个使用是为过滤器或校验器指定字段，这里过滤器或校验器要求多个字段作为输入。 如果 'fields' metacommand 是个数组，过滤器或校验器相应的参数是一个那些字段值的数组。 例如，通常用户会在两个字段中指定密码字符串，他们必需在两个字段中输入相同的字符串。 假定你实现一个校验器类，带有一个数组参数，如果数组中所有的值彼此相等，就返回 true。

<?php
$validators = array(
    'password' => array(
        'StringEquals',
        'fields' => array('password1', 'password2')
    )
);
// Invokes hypothetical class Zend_Validate_StringEquals, passing an array argument
// containing the values of the two input data fields named 'password1' and 'password2'.

如果这个规则校验失败，规则键（'password'）用于 getInvalid() 的返回值，不是命名在 'fields' metacommand 中的其它字段。

The PRESENCE metacommand

在校验器数组里的每个条目可能有一个叫做 'presence' 的 metacommand。 如果这个 metacommand 的值是 'required'，那么字段必需存在于输入数据， 否则，就报告为丢失字段。

你可以用类常量 Zend_Filter_Input::PRESENCE 而不是字符串来指定这个 metacommand。

<?php
$validators = array(
    'month' => array(
        'digits',
        'presence' => 'required'
    )
);

这个 metacommand 的缺省值是 'optional'。

The DEFAULT_VALUE metacommand

如果字段没有出现在输入数据里，并且你为了规则为 'default' metacommand 指定一个值， 这个字段就用 metacommand 的值。

你可以用类常量 Zend_Filter_Input::DEFAULT_VALUE 而不是字符串来指定这个 metacommand。

在任何校验器被调用之前，这个缺省值被分配给字段。缺省值只为当前规则应用于字段， 如果同样的字段在后来的规则被引用，当评估规则时字段没有值。 这样，对于给定的字段不同的规则可以声明不同的缺省值。

<?php
$validators = array(
    'month' => array(
        'digits',
        'default' => '1'
    )
);

// no value for 'month' field
$data = array();

$input = new Zend_Filter_Input(null, $validators, $data);
echo $input->month; // echoes 1

如果你的规则使用 FIELDS metacommand 来定义多重字段的数组， 你可以为 DEFAULT_VALUE metacommand 定义一个数组并且相应键的缺省用于任何丢失的字段。 如果 FIELDS 定义多重字段但 DEFAULT_VALUE 是个标量，那么 缺省值用于任何在数组中的丢失的字段。

这个 metacommand 没有缺省值。

The ALLOW_EMPTY metacommand

缺省地，如果一个字段存在于输入数据，那么校验器就应用其上，即使字段值是空的（''）。 这可能导致一个校验失败，例如：如果校验器检查数字字符，并且因为零长度字符串是没有字符，那么校验器就报告数据错误。

如果读你来说空字符应当认为有效，你可以设置 metacommand 'allowEmpty' 为 true。 这样空字符的输入数据就可以通过校验。

你可以用类常量 Zend_Filter_Input::ALLOW_EMPTY 而不是字符串来指定这个 metacommand。

<?php
$validators = array(
    'address2' => array(
        'Alnum',
        'allowEmpty' => true
    )
);

这个 metacommand 的缺省值是 false。

在非正常情况下你声明没有校验器的校验规则，但 'allowEmpty' metacommand 是 false （即如果字段是空的就被认为无效）， Zend_Filter_Input 返回缺省错误消息，你可以用 getMessages() 来读取。 你可以用 'notEmptyMessage' 选项作为 Zend_Filter_Input 构造器的参数或使用 setOptions() 方法来指定这个消息。

<?php
$options = array(
    'notEmptyMessage' => "A non-empty value is required for field '%field%'"
);

$input = new Zend_Filter_Input($filters, $validators, $data, $options);

// alternative method:

$input = new Zend_Filter_Input($filters, $validators, $data);
$input->setOptions($options);

The BREAK_CHAIN metacommand

缺省地，如果一个规则有多于一个校验器，所有校验器应用于输入，并且返回的消息包含所有由输入导致的错误消息。

另外，如果 'breakChainOnFailure' metacommand 的值是 true， 校验器链在第一次校验失败时就终止，输入数据不再被链中的后来的校验器检查， 即使你纠正被报告的那一个，也很可能导致更多的冲突。

你可以用类常量 Zend_Filter_Input::BREAK_CHAIN 而不是字符串来指定这个 metacommand。

<?php
$validators = array(
    'month' => array(
        'Digits',
        new Zend_Validate_Between(1,12),
        new Zend_Validate_GreaterThan(0),
        'breakChainOnFailure' => true
    )
);
$input = new Zend_Filter_Input(null, $validators);

这个 metacommand 的缺省值是 false。

校验器链类 Zend_Validate 在中断链执行方面比 Zend_Filter_Input 更灵活。 对于前者，你可以设置选项来对链中每个校验器独立地根据失败来中断链。 对于后者，'breakChainOnFailure' metacommand 的定义值对规则来说一律适用所有规则中的校验器。 如果你需要更灵活的用法，要创建自己的校验器链，在校验器规则定义里把它用作一个对象：

<?php
// Create validator chain with non-uniform breakChainOnFailure attributes
$chain = new Zend_Validate();
$chain->addValidator(new Zend_Validate_Digits(), true);
$chain->addValidator(new Zend_Validate_Between(1,12), false);
$chain->addValidator(new Zend_Validate_GreaterThan(0), true);

// Declare validator rule using the chain defined above
$validators = array(
    'month' => $chain
);
$input = new Zend_Filter_Input(null, $validators);

The MESSAGES metacommand

你可以使用 metacommand 'messages' 为在规则中的每个校验器指定错误消息。 这个 metacommand 的值在规则中根据你是否有多重校验器而不同， 或者如果你想在给定的校验器中为特定错误条件设置消息。

你可以用类常量 Zend_Filter_Input::MESSAGES 而不是字符串来指定这个 metacommand。

下面是为单个校验器设置缺省错误消息的例子。

<?php
$validators = array(
    'month' => array(
        'digits',
        'messages' => 'A month must consist only of digits'
    )
);

如果你想给多重校验器设置错误消息，对 'messages' metacommand 的值应当使用一个数组。

这个数组的每个元素应用于在同一索引位置的校验器。你可以通过把值 n 作为数组索引为在 n 位置的校验器指定消息。 这样当在链中为后来的校验器设置消息，一些校验器就使用它们自己的缺省消息。

<?php
$validators = array(
    'month' => array(
        'digits',
        new Zend_Validate_Between(1, 12),
        'messages' => array(
            // use default message for validator [0]
            // set new message for validator [1]
            1 => 'A month value must be between 1 and 12'
        )
    )
);

如果你的校验器其中一个有多重错误消息，它们由消息键来识别。 在每个校验器类里有不同的键，作为识别器服务于各自校验器类可能产生的错误消息。 每个校验类为它的消息键定义常量。你可以通过传递关联数组而不是字符串来在 'messages' metacommand 里使用这些键。

<?php
$validators = array(
    'month' => array(
        'digits', new Zend_Validate_Between(1, 12),
        'messages' => array(
            'A month must consist only of digits',
            array(
                Zend_Validate_Between::NOT_BETWEEN =>
                    'Month value %value% must be between %min% and %max%',
                Zend_Validate_Between::NOT_BETWEEN_STRICT =>
                    'Month value %value% must be strictly between %min% and %max%'
            )
        )
    )
);

你应当参考每个校验器类的文档来获知它是否有多重错误消息、这些消息的键和可用于消息模板的令牌。

对所有的规则使用选项来设置 metacommands

'allowEmpty'、 'breakChainOnFailure' 和 'presence' metacommands 的缺省值可以使用 Zend_Filter_Input 构造器的 $options 参数来为所有的规则设置。 它让你为所有的规则设置缺省值而不需要为每个规则设置 metacommand。

<?php
// The default is set so all fields allow an empty string.
$options = array('allowEmpty' => true);

// You can override this in a rule definition,
// if a field should not accept an empty string.
$validators = array(
    'month' => array(
        'Digits',
        'allowEmpty' => false
    )
);

$input = new Zend_Filter_Input($filters, $validators, $data, $options);

'fields'、'messages' 和 'default' metacommands 不能用这个技术来设置。

添加过滤器类命名空间

缺省地，当声明一个过滤器或校验器为一个字符串，Zend_Filter_Input 就搜索在 Zend_Filter 或 Zend_Validate 命名空间下的相应的类。 例如：名为字符串 'digits' 的过滤器在 Zend_Filter_digits 类中。

如果你写自己的过滤器或校验器类，或使用由第三方提供的过滤器或校验器，这些类存在于不同于 Zend_Filter 或 Zend_Validate 的命名空间。 你可以告诉 Zend_Filter_Input 搜索更多的命名空间， 你可以在构造器选项里指定命名空间：

<?php
$options = array('inputNamespace' => 'My_Namespace');
$input = new Zend_Filter_Input($filters, $validators, $data, $options);

另外，你可以使用 addNamespace() 方法：

<?php
$input->addNamespace('Other_Namespace');

// Now the search order is:
// 1. My_Namespace
// 2. Other_Namespace
// 3. Zend_Filter
// 4. Zend_Validate

你不能删除 Zend_Filter 和 Zend_Validate 的命名空间，只可以添加命名空间，系统首先搜索用户定义的命名空间，然后搜索 Zend 命名空间。

Note: 从版本 1.0.4 开始， Zend_Filter_Input::NAMESPACE, 把值 namespace 改成 Zend_Filter_Input::INPUT_NAMESPACE，使用值 inputNamespace 是为了服从 PHP 5.3 的保留字 namespace 。

编写过滤器
Zend_Filter
Zend Framework手册 中文版
Zend_Filter_Inflector
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Filter
  • 简介
  • 标准过滤器类
  • 过滤器链
  • 编写过滤器
  • Zend_Filter_Input
  • Zend_Filter_Inflector


编写过滤器 - Zend Framework Manual

过滤器链
Zend_Filter
Zend Framework手册 中文版
Zend_Filter_Input

编写过滤器

Zend_Filter提供了一系列常用的过滤器，但是开发者经常需要为他们特殊的用例编写定制的过滤器。编写定制的过滤器很容易，只要实现Zend_Filter_Interface接口。

Zend_Filter_Interface接口定义了一个方法filter()，可被用户的类实现。使用Zend_Filter::addFilter()方法，可以把一个实现了这个接口的对象添加到过滤器链中。

下面的例子，示范了怎样编写一个定制的过滤器：

class MyFilter implements Zend_Filter_Interface
{
    public function filter($value)
    {
        // perform some transformation upon $value to arrive on $valueFiltered

        return $valueFiltered;
    }
}

添加上述过滤器的实例到过滤器链中：

$filterChain = new Zend_Filter();
$filterChain->addFilter(new MyFilter());

过滤器链
Zend_Filter
Zend Framework手册 中文版
Zend_Filter_Input
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Filter
  • 简介
  • 标准过滤器类
  • 过滤器链
  • 编写过滤器
  • Zend_Filter_Input
  • Zend_Filter_Inflector


Zend_Form - Zend Framework Manual

Zend_Filter_Inflector
Zend Framework Reference
Zend Framework手册 中文版
Zend_Form

Zend_Form

Table of Contents
  • Zend_Form
  • Zend_Form 快速起步
  • 使用 Zend_Form_Element 生成表单元素
  • 使用 Zend_Form 生成表单
  • 使用 Zend_Form_Decorator 生成定制的表单标识（Markup）
  • Zend Framework 带有的标准表单元素
  • Zend Framework 带有的标准表单装饰器（Decorators）
  • Zend_Form 的国际化
  • Zend_Form 的高级用法
Zend_Filter_Inflector
Zend Framework Reference
Zend Framework手册 中文版
Zend_Form
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


Zend_Form - Zend Framework Manual

Zend_Form
Zend_Form
Zend Framework手册 中文版
Zend_Form 快速起步

Zend_Form

Zend_Form 在 web 程序中简化表单的创建和处理，它完成下列目标：

  • 元素输入过滤和校验

  • 元素排序

  • 元素和表单解析（rendering），包括转义（escaping）

  • 元素和表单分组

  • 元素和表单级配置

它充分利用了其它 Zend Framework 组件来完成其目标，包括：Zend_Config、 Zend_Validate、Zend_Filter、 Zend_Loader_PluginLoader 和 可选的 Zend_View。

Zend_Form
Zend_Form
Zend Framework手册 中文版
Zend_Form 快速起步
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Form
  • Zend_Form
  • Zend_Form 快速起步
  • 使用 Zend_Form_Element 生成表单元素
  • 使用 Zend_Form 生成表单
  • 使用 Zend_Form_Decorator 生成定制的表单标识（Markup）
  • Zend Framework 带有的标准表单元素
  • Zend Framework 带有的标准表单装饰器（Decorators）
  • Zend_Form 的国际化
  • Zend_Form 的高级用法


Zend_Form 快速起步 - Zend Framework Manual

Zend_Form
Zend_Form
Zend Framework手册 中文版
使用 Zend_Form_Element 生成表单元素

Zend_Form 快速起步

本快速起步指南覆盖使用 Zend_Form 创建、校验和解析表单的基础。

创建表单对象

创建表单对象非常简单：只要实现 Zend_Form：

<?php
$form = new Zend_Form;
?>

对于高级用例，需要创建 Zend_Form 的子类，但对于简单的表单，程序可以用 Zend_Form 的对象来创建。

如果想指定表单的动作和方法（总是好主意），用 setAction() 和 setMethod() 来完成：

<?php
$form->setAction('/resource/process')
     ->setMethod('post');
?>

上述代码设置表单动作为部分 URL "/resource/process" 和表单方法为 HTTP POST，这将在解析的最后期间表现出来。

你可以通过使用 setAttrib() 或 setAttribs() 方法为 <form> 标签设置另外的 HTML 属性，例如：如果想设置 id, 则设置 "id" 属性：

<?php
$form->setAttrib('id', 'login');
?>

添加表单元素

没有元素，表单就什么都不是。Zend_Form 带有一些缺省的通过 Zend_View 助手解析 XHTML 的元素：

  • button

  • checkbox (or many checkboxes at once with multiCheckbox)

  • hidden

  • image

  • password

  • radio

  • reset

  • select (both regular and multi-select types)

  • submit

  • text

  • textarea

有两个方法添加表单元素：实例化具体的元素并传递这些对象，或者传递元素类型并使 Zend_Form 实例化一个正确类型的对象。

一些例子：

<?php
// Instantiating an element and passing to the form object:
$form->addElement(new Zend_Form_Element_Text('username'));

// Passing a form element type to the form object:
$form->addElement('text', 'username');
?>

缺省地，这些没有校验器和过滤器，你需要用最基本的校验器和可能的过滤器来配置元素。有三个方法：(a) 在传递元素给表单之前，(b) 通过用 Zend_Form 创建元素时传递的配置选项，(c) 从表单把元素拉出来并在以后配置。

让我们首先看看为一个具体的元素实例创建校验器。可以传递 Zend_Validate_* 对象，或校验器的名称：

<?php
$username = new Zend_Form_Element_Text('username');

// Passing a Zend_Validate_* object:
$username->addValidator(new Zend_Validate_Alnum());

// Passing a validator name:
$username->addValidator('alnum');
?>

当使用第二个方法，如果校验器可接受构造器参数，可以把它们放到数组里作为第三个参数：

<?php
// Pass a pattern
$username->addValidator('regex', false, array('/^[a-z]/i'));
?>

（第二个参数用来指示是否这个校验失败时停止后面的校验，缺省为 false。）

你也可能希望指定一个必需的元素，可以通过使用访问器或当创建该元素时传递一个选项来完成，在前面的例子中：

<?php
// 使这个元素成为必需：
$username->setRequired(true);
?>

当一个元素是必需的，一个 'NotEmpty' 校验器被添加到校验器链的顶部，确保该元素有一个值。

过滤器会像校验器一样注册，为了演示，让我们添加一个来把最终值变小写的过滤器：

<?php
$username->addFilter('StringtoLower');
?>

这样，最终元素设置看起来像这样：

<?php
$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'));
?>

就算这样简单，在表单中为每个元素都做这样的工作也是单调乏味的。让我们试一试上述的方法(b)，当使用工厂模式 Zend_Form::addElement() 创建一个新元素，我们可以可选地传递配置选项，包括校验器和过滤器。这样，可以简单地完成上述任务：

<?php
$form->addElement('text', 'username', array(
    'validators' => array(
        'alnum',
        array('regex', false, '/^[a-z]/i')
    ),
    'required' => true,
    'filters'  => array('StringToLower'),
));
?>

Note: 如果你发现在许多地方用同样的选项来设置元素，可以考虑创建自己的 Zend_Form_Element 的子类并使用它，这样长远来说会减少很多打字的任务。

解析（Render）表单

解析表单很简单，大部分元素使用 Zend_View 助手来解析，这样需要视图对象来解析。除了这以外，还有两个方法：使用表单的 render() 方法或简单地 echo 它。

<?php
// Explicitly calling render(), and passing an optional view object:
echo $form->render($view);

// Assuming a view object has been previously set via setView():
echo $form;
?>

缺省地，Zend_Form 和 Zend_Form_Element 将企图使用在 ViewRenderer 中初始化过的视图对象，你不需要在Zend Framework MVC 中手工设置视图。在视图脚本中解析表单是如此的简单：

<?= $this->form ?>

在内部，Zend_Form 使用 "decorators" （装饰器） 来执行解析，这些装饰器可以替换内容、追加内容或预先准备内容，并拥有传递给它们的元素的 full introspection 。结果，你可以组合多个装饰器来完成定制效果。缺省地，Zend_Form_Element 实际上组合了四个装饰器来完成输出，参见下例的设置：

<?php
$element->addDecorators(array(
    'ViewHelper',
    'Errors',
    array('HtmlTag', array('tag' => 'dd')),
    array('Label', array('tag' => 'dt')),
));
?>

（ <HELPERNAME> 是视图助手的名称，并根据元素不同而不同）

上述的例子创建的输出如下：

<dt><label for="username" class="required">Username</dt>
<dd>
    <input type="text" name="username" value="123-abc" />
    <ul class="errors">
        <li>'123-abc' has not only alphabetic and digit characters</li>
        <li>'123-abc' does not match against pattern '/^[a-z]/i'</li>
    </ul>
</dd>

（虽然没有使用相同的格式。）

如果你想输出不同的东西，可以修改由元素使用的装饰器，参见装饰器一节有更多内容。

表单循环检查所有元素，并把它们放到 HTML <form>。当设置表单时，你提供的动作和方法被提供给 <form> 标签，还有任何通过 setAttribs() 和它的家族设置的属性。

元素或者按注册的顺序循环，或者如果元素包含顺序属性，就按这个顺序循环。可以使用下列方法设置元素顺序：

<?php
$element->setOrder(10);
?>

或者，当创建元素，作为一个选项传递给它：

<?php
$form->addElement('text', 'username', array('order' => 10));
?>

检查表单是否有效

表单提交之后，需要检查它是否能通过校验。每个元素根据提供的数据来检查，如果匹配元素名的键没有出现，并该条目被标记为必需，就用 null 值来校验。

数据从哪里来？用 $_POST 或 $_GET 或者其它手头上的数据源 （例如 web 服务请求）：

<?php
if ($form->isValid($_POST)) {
    // success!
} else {
    // failure!
}
?>

用 AJAX 请求， 有时候可以侥幸成功校验单个元素或一组元素。isValidPartial() 将校验局部的表单，不像 isValid()，如果特定的键没有出现，那个特定部分的元素就不校验：

<?php
if ($form->isValidPartial($_POST)) {
    // elements present all passed validations
} else {
    // one or more elements tested failed validations
}
?>

一个可选的方法，processAjax()，也可以用来校验局部表单，不像 isValidPartial()，如果失败，它返回一个包含错误消息的 JSON 格式的字符串。

假设校验都通过，现在就可以取得过滤后的值：

<?php
$values = $form->getValues();
?>

如果任何时候需要没有过滤的值，使用：

<?php
$unfiltered = $form->getUnfilteredValues();
?>

获得错误状态

如果表单校验失败，在大多数情况下，可以再次解析表单，如果使用了缺省的装饰器，错误信息就会显示出来：

<?php
if (!$form->isValid($_POST)) {
    echo $form;

    // or assign to the view object and render a view...
    $this->view->form = $form;
    return $this->render('form');
}
?>

如果想插入错误消息，有两个方法： getErrors() 返回一个元素名/代码对的联合数组（这里的代码是指一个错误代码数组）。getMessages() 返回一个元素名/消息对的联合数组（这里的消息是指错误代码/错误消息对的联合数组）。如果给定的元素没有任何错误，数组就不包含它。

放到一起

来创建一个简单的登录表单，我们需要这些元素：

  • username

  • password

  • submit

让我们假设有效的用户名应当只是字母数字字符，以字母开头，最少 6 个字符，最长 20 个字符，最后格式化成小写；密码最少 6 个字符，当完成这些，我们就提交，保持未校验。

我们使用 Zend_Form 的配置选项的能力来建立表单：

<?php

$form = new Zend_Form();
$form->setAction('/user/login')
     ->setMethod('post');

// Create and configure username element:
$username = $form->createElement('text', 'username');
$username->addValidator('alnum')
         ->addValidator('regex', false, array('/^[a-z]+/'))
         ->addValidator('stringLength', false, array(6, 20))
         ->setRequired(true)
         ->addFilter('StringToLower');

// Create and configure password element:
$password = $form->createElement('password', 'password');
$password->addValidator('StringLength', false, array(6))
         ->setRequired(true);

// Add elements to form:
$form->addElement($username)
     ->addElement($password)
     // use addElement() as a factory to create 'Login' button:
     ->addElement('submit', 'login', array('label' => 'Login'));
?>

接着，我们将创建控制器来处理这些：

<?php
class UserController extends Zend_Controller_Action
{
    public function getForm()
    {
        // create form as above
        return $form;
    }

    public function indexAction()
    {
        // render user/form.phtml
        $this->view->form = $this->getForm();
        $this->render('form');
    }

    public function loginAction()
    {
        if (!$this->getRequest()->isPost()) {
            return $this->_forward('index');
        }
        $form = $this->getForm();
        if (!$form->isValid($_POST)) {
            // Failed validation; redisplay form
            $this->view->form = $form;
            return $this->render('form');
        }

        $values = $form->getValues();
        // now try and authenticate....
    }
}
?>

和一个视图脚本来显示表单：

<h2>Please login:</h2>
<?= $this->form ?>

注意在控制器代码中，还有很多需要做：例如在提交后，需要用 Zend_Auth 来认证。

使用 Zend_Config 对象

所有 Zend_Form 类可以用 Zend_Config 来配置，可以传递 Zend_Config 对象给构造器或者通过 setConfig() 来传递。来看一下如何用 INI 文件来创建上述表单，首先，遵循建议，把配置放到反映发行位置的节里面，并集中到 'development' 节，接着，为给定控制器（'user'）设置一个节，为表单（'login'）设置一个键：

[development]
; general form metainformation
user.login.action = "/user/login"
user.login.method = "post"

; username element
user.login.elements.username.type = "text"
user.login.elements.username.options.validators.alnum.validator = "alnum"
user.login.elements.username.options.validators.regex.validator = "regex"
user.login.elements.username.options.validators.regex.options.pattern = "/^[a-z]/i"
user.login.elements.username.options.validators.strlen.validator = "StringLength"
user.login.elements.username.options.validators.strlen.options.min = "6"
user.login.elements.username.options.validators.strlen.options.max = "20"
user.login.elements.username.options.required = true
user.login.elements.username.options.filters.lower.filter = "StringToLower"

; password element
user.login.elements.password.type = "password"
user.login.elements.password.options.validators.strlen.validator = "StringLength"
user.login.elements.password.options.validators.strlen.options.min = "6"
user.login.elements.password.options.required = true

; submit element
user.login.elements.submit.type = "submit"

接着，你可以把它传递给表单构造器：

<?php
$config = new Zend_Config_Ini($configFile, 'development');
$form   = new Zend_Form($config->user->login);
?>

整个表单就定义好了。

结论

希望通过这个小教程，你能接触和理解 Zend_Form 的强大和灵活性，然后接着读更深的资料！

Zend_Form
Zend_Form
Zend Framework手册 中文版
使用 Zend_Form_Element 生成表单元素
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Form
  • Zend_Form
  • Zend_Form 快速起步
  • 使用 Zend_Form_Element 生成表单元素
  • 使用 Zend_Form 生成表单
  • 使用 Zend_Form_Decorator 生成定制的表单标识（Markup）
  • Zend Framework 带有的标准表单元素
  • Zend Framework 带有的标准表单装饰器（Decorators）
  • Zend_Form 的国际化
  • Zend_Form 的高级用法


使用 Zend_Form_Element 生成表单元素 - Zend Framework Manual

Zend_Form 快速起步
Zend_Form
Zend Framework手册 中文版
使用 Zend_Form 生成表单

使用 Zend_Form_Element 生成表单元素

表单由元素组成，它一般对应于 HTML 表单输入。Zend_Form_Element 封装了单个表单元素，并完成下列工作：

  • 校验（提交的数据有效乎？）

    • 抓取校验错误代码和消息

  • 过滤（在校验和/或输出之前元素如何转义或规范化？）

  • 解析（元素如何显示？）

  • 元数据和属性（什么信息进一步修饰元素？）

基础类 Zend_Form_Element 对许多类有合理的缺省设置，但最好还是继承这个类来完成特殊意图的元素。另外，Zend Framework 带有许多标准的 XHTML 元素，请阅读 在标准元素一章 的有关文档。

插件加载器

Zend_Form_Element 利用 Zend_Loader_PluginLoader 来使开发者指定替代校验器、过滤器和装饰器的位置。每个都有它自己携带的插件加载器，并使用通用的访问器来读取或修改它们。

下列加载器类型和各种各样的插件加载器方法一起使用：'validate'、 'filter' 和 'decorator'。类型名是大小写敏感的。

和插件加载器交互使用的方法如下：

  • setPluginLoader($loader, $type)：$loader 是插件加载器对象自己，而 $type 是上述类型之一。这个方法为给定类型的插件加载器设置为最新的特定的载器对象。

  • getPluginLoader($type): 用携带的 $type 来读取插件加载器。

  • addPrefixPath($prefix, $path, $type = null): 添加 prefix/path 联合给由 $type 指定的加载器。如果 $type 是 null，它将尝试通过追加前缀给 "_Validate"、"_Filter", 和 "_Decorator" 来添加路径到所有加载器，并用 "Validate/"、"Filter/" 和 "Decorator/". 追加路径。如果你在通用的等级下有所有额外的表单元素类，这是个用来设置基础前缀给它们的方便的方法。

  • addPrefixPaths(array $spec): 让你一次性添加许多路径给一个或多个插件加载器。它需要每个数组条目是个带有 'path'、'prefix' 和 'type'. 键的数组。

定制的校验器、过滤器和装饰器是在表单和封装定制功能之间共享功能的简单的办法。

Example #1 定制标签

插件的一个普通用例是来为标准类提供替换。例如，如果想实现一个不同的 'Label' 装饰器 －－ 如总要追加冒号 －－你可以创建你自己的带有类前缀的 'Label' 装饰器，然后把它加到你的前缀路径。

让我们从定制标签装饰器来开始，给它一个类前缀 "My_Decorator"，类文件就是 "My/Decorator/Label.php"。

<?php
class My_Decorator_Label extends Zend_Form_Decorator_Abstract
{
    protected $_placement = 'PREPEND';

    public function render($content)
    {
        if (null === ($element = $this->getElement())) {
            return $content;
        }
        if (!method_exists($element, 'getLabel')) {
            return $content;
        }

        $label = $element->getLabel() . ':';

        if (null === ($view = $element->getView())) {
            return $this->renderLabel($content, $label);
        }

        $label = $view->formLabel($element->getName(), $label);

        return $this->renderLabel($content, $label);
    }

    public function renderLabel($content, $label)
    {
        $placement = $this->getPlacement();
        $separator = $this->getSeparator();

        switch ($placement) {
            case 'APPEND':
                return $content . $separator . $label;
            case 'PREPEND':
            default:
                return $label . $separator . $content;
        }
    }
}

现在，当元素寻找装饰器时，就使用这个插件路径：

$element->addPrefixPath('My_Decorator', 'My/Decorator/', 'decorator');

另外，我们可以在表单一级来做以确保所有的装饰器使用这个路径：

$form->addElementPrefixPath('My_Decorator', 'My/Decorator/', 'decorator');

用这个添加的路径，当添加一个装饰器，将首先搜索 'My/Decorator/' 路径来检查是否存在装饰器。结果，如果请求 'Label' 装饰器，'My_Decorator_Label' 将被使用。

过滤器

在校验之前对输入执行规范化常常是有用的并/或必需的 － 例如，你可能想要剥离所有 HTML，在剩下的东东上运行校验来确保提交有效。或者你可能想把输入的数据两边的空格都消掉，这样 StringLength 校验器就不会返回失败。这些操作使用 Zend_Filter 来执行，并且 Zend_Form_Element 对过滤链有支持，让你指定多个连续的过滤器来用。在校验期间和通过 getValue() 读取元素值的时候都会发生校验：

<?php
$filtered = $element->getValue();
?>

有两个办法添加过滤器：

  • 传递一个具体的过滤器实例

  • 提供过滤器名称 － 短名或完整的类名都可以

看一些例子：

<?php
// 具体的过滤器实例：
$element->addFilter(new Zend_Filter_Alnum());

// 合格的全类名：
$element->addFilter('Zend_Filter_Alnum');

// 短过滤器名：
$element->addFilter('Alnum');
$element->addFilter('alnum');
?>

短名一般就是过滤器名去掉前缀，缺省就是去掉 'Zend_Filter_' 前缀。另外，首字母不需要大写。

Note: 使用定制的过滤器类
如果你有自己的一组过滤器，可以通过 addPrefixPath() 来告诉 Zend_Form_Element。例如，如果你在 'My_Filter' 前缀下有过滤器，这样来告诉 Zend_Form_Element：

<?php
$element->addPrefixPath('My_Filter', 'My/Filter/', 'filter');
?>
（回忆一下第三个参数用来指示哪个是执行这个动作的插件加载器）

任何时候需要非过滤的数据，使用 getUnfilteredValue() 方法：

<?php
$unfiltered = $element->getUnfilteredValue();
?>

参见 Zend_Filter 文档 有更多关于过滤器的信息。

过滤器带有这些方法：

  • addFilter($nameOfFilter, array $options = null)

  • addFilters(array $filters)

  • setFilters(array $filters) （重写所有过滤器）

  • getFilter($name) （按名字读取过滤器对象）

  • getFilters() （读取所有过滤器）

  • removeFilter($name) （按名字删除过滤器）

  • clearFilters() （删除所有过滤器）

校验器

如果你赞同安全咒语“过滤输入，转义输出”，你将会校验（“过滤输入”）你的表单输入。 在 Zend_Form 里，每个元素包含它自己的由 Zend_Validate_* 校验器组成的校验器链。

两个办法添加校验器到校验器链：

  • 传递一个具体的校验器实例

  • 提供一个校验器名 － 短名或者完整的类名都可以

看一些例子：

<?php
// Concrete validator instance:
$element->addValidator(new Zend_Validate_Alnum());

// Fully qualified class name:
$element->addValidator('Zend_Validate_Alnum');

// Short validator name:
$element->addValidator('Alnum');
$element->addValidator('alnum');
?>

短名一般就是校验器名去掉前缀，缺省就是去掉 'Zend_Validate_' 前缀。另外，首字母不需要大写。

Note: 使用定制的校验器类
如果你有自己的一组校验器，可以通过 addPrefixPath() 来告诉 Zend_Form_Element。例如，如果你在 'My_Validator' 前缀下有校验器，这样来告诉 Zend_Form_Element：

<?php
$element->addPrefixPath('My_Validator', 'My/Validator/', 'validate');
?>
（回忆一下第三个参数用来指示哪个是执行这个动作的插件加载器）

如果特定的校验失败，为阻止后面的校验工作，传递第二个参数 true （布尔型）：

<?php
$element->addValidator('alnum', true);
?>

如果你使用一个字符串名来添加一个校验器，并且这个校验器接受参数给构造器，你可以把这个第三个参数 addValidator() 作为数组传递：

<?php
$element->addValidator('StringLength', false, array(6, 20));
?>

这样传递参数应该按照它们在构造器里定义的顺序进行。上述例子将带参数 $min 和 $max 实例化 Zend_Validate_StringLenth 类：

<?php
$validator = new Zend_Validate_StringLength(6, 20);
?>

Note: 提供定制的校验错误消息
有些开发者可能想为校验器提供定制的错误消息。 Zend_Form_Element::addValidator() 的 $options 参数让你通过提供 'messages' 键并把它设置为键/值对（用来设置消息模板）的数组来完成。你需要知道特定校验器的各种各样的校验错误类型的错误代码。
稍好的选择是在表单中使用 Zend_Translate_Adapter。错误代码通过缺省的错误装饰器自动传递给适配器，然后你可以通过为你的校验器的各种错误代码设置翻译来指定自己的错误消息字符串。

你也可以使用 addValidators() 一次性设置许多校验器。基本的用法是传递数组的数组，每个数组包含 1 到 3 个匹配 addValidator() 的构造器的值：

<?php
$element->addValidators(array(
    array('NotEmpty', true),
    array('alnum'),
    array('stringLength', false, array(6, 20)),
));
?>

如果你想做的更明确和更详细，可以使用数组键 'validator'、 'breakChainOnFailure' 和 'options'：

<?php
$element->addValidators(array(
    array(
        'validator'           => 'NotEmpty',
        'breakChainOnFailure' => true),
    array('validator' => 'alnum'),
    array(
        'validator' => 'stringLength',
        'options'   => array(6, 20)),
));
?>

这个用法展示如何在配置文件中配置校验器：

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

注意每个条目有一个键，不管是否需要，这是使用配置文件规定的 －－但它也帮助清楚理解哪个参数用于什么。请记住任何校验器选项必需按顺序指定。

为校验一个元素，传递值给 isValid()：

<?php
if ($element->isValid($value)) {
    // valid
} else {
    // invalid
}
?>

Note: 在过滤后的值上校验
Zend_Form_Element::isValid() 在校验之前通过提供过滤器链来过滤（输入）值。见 See 过滤器一节 有更多信息。

Note: 校验上下文
Zend_Form_Element::isValid() 支持另外的参数 $context。当校验一个表单 Zend_Form::isValid() 传递由 $context 处理过的数据的整个数组，Zend_Form_Element::isValid() 接着把它传递给每个校验器。这意味着你可以写知道数据传递给其它表单元素的校验器，例如，标准的注册表单有密码和密码确认元素，得有一个校验它们是否匹配。这样的校验器看起来如下：

<?php
class My_Validate_PasswordConfirmation extends Zend_Validate_Abstract
{
    const NOT_MATCH = 'notMatch';

    protected $_messageTemplates = array(
        self::NOT_MATCH => 'Password confirmation does not match'
    );

    public function isValid($value, $context = null)
    {
        $value = (string) $value;
        $this->_setValue($value);

        if (is_array($context)) {
            if (isset($context['password_confirm'])
                && ($value == $context['password_confirm']))
            {
                return true;
            }
        } elseif (is_string($context) && ($value == $context)) {
            return true;
        }

        $this->_error(self::NOT_MATCH);
        return false;
    }
}
?>

校验器按顺序处理，除非用 breakChainOnFailure 为 true 创建的校验器并且校验失败，否则每个校验器都要处理。确认按合理的顺序指定你的校验器。

校验失败后，你可以从校验器链读取错误代码和消息：

<?php
$errors   = $element->getErrors();
$messages = $element->getMessages();
?>

（注意：错误消息返回的是一个有错误代码/错误消息对的联合数组）

除了校验器外，你可以用 setRequired(true) 指定必需的元素。缺省地，这个标志是 false，如果没有值传递给 isValid()，校验器链将被跳过。你也可以用许多办法来修改它的行为：

  • 缺省地，当元素是必需的，标志 'allowEmpty'也是 true。这意味着如果传递给 isValid() 的值为空，校验器将被跳过。可以用访问器 setAllowEmpty($flag) 来切换这个标志。当标志为 false，并且传递了一个值，校验器将仍然运行。

  • 缺省地，如果元素是必需的，但不包括 'NotEmpty' 校验器，isValid() 就用 breakChainOnFailure 标志设置添加一个到栈顶。这使得要求的标志有语义意义：如果没有传递值，我们立即使提交的数据无效并通知用户，并防止其它校验器继续校验我们已知的无效数据。

    如果你不想这样，传递给 setAutoInsertNotEmptyValidator($flag) 一个 false 值使它关闭。这将防止 isValid() 在校验器链里放置一个 'NotEmpty' 校验器。

关于校验器的更多信息，参见 Zend_Validate 文档 。

Note: 使用 Zend_Form_Elements 作为通用的校验器
Zend_Form_Element 实现 Zend_Validate_Interface，意味着元素可以在其它非表单相关的校验链里被用做校验器。

校验相关的方法包括：

  • setRequired($flag) 和 isRequired() 让你设置和读取 'required' 标志的状态。当设置为布尔 true，这个标志要求元素在由 Zend_Form 处理的数据中。

  • setAllowEmpty($flag) 和 getAllowEmpty() 让你修改可选元素的行为（例如，要求的标志为 false 的元素）。当 'allow empty' 标志为 true 时，空值将传递给校验器链。

  • setAutoInsertNotEmptyValidator($flag) 当元素是必需时，让你指定是否 'NotEmpty' 校验器预先准备给校验器链。缺省地，这个标志为 true 。

  • addValidator($nameOrValidator, $breakChainOnFailure = false, array $options = null)

  • addValidators(array $validators)

  • setValidators(array $validators) （重写所有校验器）

  • getValidator($name) （按名读取校验器对象）

  • getValidators() （读取所有校验器）

  • removeValidator($name) （按名删除校验器）

  • clearValidators() （删除所有校验器）

定制错误消息

有时，你想定制一条或多条特定的错误消息来替代由附加到元素上的校验器所带的错误消息。 另外，有时候你想自己标记表单无效，从 1.6.0 版开始，通过下列方法来实现这个功能。

  • addErrorMessage($message): 添加一条来显示当校验失败时的错误消息。 可以多次调用，新消息就追加到堆栈。

  • addErrorMessages(array $messages): 添加多条错误消息来显示校验错误。

  • setErrorMessages(array $messages): 添加多条错误消息来显示校验错误，并覆盖先前的错误消息。

  • getErrorMessages(): 读取已定义的定制的错误消息列表。

  • clearErrorMessages(): 删除已定义的定制的错误消息。

  • markAsError(): 标记表单已经有失败的校验。

  • hasErrors(): 确定是否元素有失败校验或标记为无效。

  • addError($message): 添加一条消息给定制错误消息栈并标记表单无效。

  • addErrors(array $messages): 添加数条消息给定制错误消息栈并标记表单无效。

  • setErrors(array $messages): 覆盖定制的错误消息堆栈并标记表单无效。

所有用这个方式设置的错误可以被翻译。

装饰器

对许多 web 开发者来说一个特别的痛苦是 XHTML 表单自己的生成。对于每个元素，开发者需要为元素自己生成 markup，label 是一个典型，并且，如果他们对用户很好，需要为显示校验错误消息生成 markup。在页面元素越多，任务就越不琐碎。

Zend_Form_Element 试图用 "装饰器" 来解决这个问题。装饰器就是个类，可以访问元素和用于解析内容的方法。更多关于装饰器如何工作，参见 Zend_Form_Decorator。

Zend_Form_Element 所使用的缺省的装饰器是：

  • ViewHelper: 指定一个视图助手用于解析元素。'helper' 元素属性可用来指定使用哪个视图助手。缺省地，Zend_Form_Element 指定 'formText' 视图助手，但个别的子类指定不同的助手。

  • Errors: 使用 Zend_View_Helper_FormErrors 追加错误消息给元素，如果没有错误，就不追加。

  • HtmlTag: 在一个 HTML <dd> 标签里封装元素和错误。

  • Label: 使用 Zend_View_Helper_FormLabel 预先准备一个标签给元素，并把它封装在一个 <dt> 标签里。如果没有提供标签（Label），就解析定义术语（definition term）标签（tag）。

Note: 不需要加载缺省装饰器
缺省地，在对象初始化过程中加载缺省装饰器。你可以通过传递 'disableLoadDefaultDecorators' 选项给构造器来关闭它：

<?php
$element = new Zend_Form_Element('foo', array('disableLoadDefaultDecorators' => true));
该选项可以和企图选项混合，它们都是数组选项或在 Zend_Config 对象里。

因为装饰器注册顺序的原因 －－先注册先执行－－你需要确保按合适的顺序来注册装饰器，或者确保以健全的方式设置替换选项。这个是注册缺省装饰器的例子：

<?php
$this->addDecorators(array(
    array('ViewHelper'),
    array('Errors'),
    array('HtmlTag', array('tag' => 'dd')),
    array('Label', array('tag' => 'dt')),
));
?>

初始内容由 'ViewHelper' 装饰器生成，它生成表单元素自己。接着，'Errors' 装饰器从元素里抓取错误消息。如果有任何错误，就传递给 'FormErrors' 视图助手来解析。下一个装饰器 'HtmlTag' 在一个 HTML <dd> 标签里封装元素和错误。最后，'label' 装饰器读取元素的标签并传递给 'FormLabel' 视图助手，封装在一个 HTML <dt> 标签里。缺省地，数据预先准备给内容，输出结果基本上是这样的：

<dt><label for="foo" class="optional">Foo</label></dt>
<dd>
    <input type="text" name="foo" id="foo" value="123" />
    <ul class="errors">
        <li>"123" is not an alphanumeric value</li>
    </ul>
</dd>

关于装饰器的更多信息，请阅读 Zend_Form_Decorator 一节。

Note: 使用同类型的多重装饰器
在内部，当读取装饰器时，Zend_Form_Element 使用装饰器的类作为查询机制。结果，你不能注册同类型的多重装饰器，后来的装饰器就重写以前存在的装饰器。
为解决这个问题，你可以使用 aliases。不是传递装饰器或装饰器名作为第一个参数给 addDecorator()，而是传递带有一个单个元素的数组，并且别名指向装饰器对象或名字：

<?php
// Alias to 'FooBar':
$element->addDecorator(array('FooBar' => 'HtmlTag'), array('tag' => 'div'));

// And retrieve later:
$decorator = $element->getDecorator('FooBar');
?>
在 addDecorators() 和 setDecorators() 方法中，你需要在表示装饰器的数组中传递 'decorator' 选项：
<?php
// Add two 'HtmlTag' decorators, aliasing one to 'FooBar':
$element->addDecorators(
    array('HtmlTag', array('tag' => 'div')),
    array(
        'decorator' => array('FooBar' => 'HtmlTag'),
        'options' => array('tag' => 'dd')
    ),
);

// And retrieve later:
$htmlTag = $element->getDecorator('HtmlTag');
$fooBar  = $element->getDecorator('FooBar');
?>

装饰器带有的方法包括：

  • addDecorator($nameOrDecorator, array $options = null)

  • addDecorators(array $decorators)

  • setDecorators(array $decorators) （重写所有装饰器）

  • getDecorator($name) （按名读取装饰器对象）

  • getDecorators() （读取所有装饰器）

  • removeDecorator($name) （按名删除装饰器）

  • clearDecorators() （删除所有装饰器）

元数据和属性

Zend_Form_Element 处理广泛的属性和元素元数据，基本属性包括：

  • name: 元素名，使用 setName() 和 getName() 访问器。

  • label: 元素标签，使用 setLabel() 和 getLabel() 访问器。

  • order: 在表单中出现的元素的索引，使用 setOrder() 和 getOrder() 访问器。

  • value: 当前元素的值，使用 setValue() 和 getValue() 访问器。

  • description: 元素的描述，常用于提供工具提示或 javascript 上下文提示，描述元素的意图，使用 setDescription() 和 getDescription() 访问器。

  • required: 当执行表单校验时，指示元素是否必需的标志，使用 setRequired() 和 getRequired() 访问器，缺省为 false。

  • allowEmpty: 指示可选的元素是否应该校验空值的标志，当为 true，并且要求的标志为 false，空值就不传递给校验器链，并假定为 true。使用 setAllowEmpty() 和 getAllowEmpty() 访问器，缺省为 true。

  • autoInsertNotEmptyValidator: 当元素是必需时，指示是否插入一个 'NotEmpty' 校验器。缺省地，这个标志为 true，用 setAutoInsertNotEmptyValidator($flag) 来设置该标志并用 autoInsertNotEmptyValidator() 来确定它的值。

表单元素可能要求另外的元数据。例如，对于 XHTML 表单元素，你可能想指定属性如类或 id，有一组访问器来完成它：

  • setAttrib($name, $value): 添加属性

  • setAttribs(array $attribs): 像 addAttribs() 一样，但重写

  • getAttrib($name): 读取一个单个的属性值

  • getAttribs(): 以键/值对读取所有属性

然而大多数时候，你可以把它们当作对象属性来访问，因为 Zend_Form_Element 利用重载来简便访问它们：

<?php
// Equivalent to $element->setAttrib('class', 'text'):
$element->class = 'text;
?>

缺省地，在解析过程中所有属性传递给由元素使用的视图助手，并当作该元素标签的 HTML 属性来解析。

标准元素

Zend_Form 带有许多标准元素，请阅读 标准元素 一章有全部细节。

Zend_Form_Element 方法

Zend_Form_Element 有许多许多方法。下面是一个快速概要，按类分组：

  • 配置：

    • setOptions(array $options)

    • setConfig(Zend_Config $config)

  • I18n:

    • setTranslator(Zend_Translate_Adapter $translator = null)

    • getTranslator()

    • setDisableTranslator($flag)

    • translatorIsDisabled()

  • 属性：

    • setName($name)

    • getName()

    • setValue($value)

    • getValue()

    • getUnfilteredValue()

    • setLabel($label)

    • getLabel()

    • setDescription($description)

    • getDescription()

    • setOrder($order)

    • getOrder()

    • setRequired($flag)

    • getRequired()

    • setAllowEmpty($flag)

    • getAllowEmpty()

    • setAutoInsertNotEmptyValidator($flag)

    • autoInsertNotEmptyValidator()

    • setIgnore($flag)

    • getIgnore()

    • getType()

    • setAttrib($name, $value)

    • setAttribs(array $attribs)

    • getAttrib($name)

    • getAttribs()

  • 插件加载器和路径：

    • setPluginLoader(Zend_Loader_PluginLoader_Interface $loader, $type)

    • getPluginLoader($type)

    • addPrefixPath($prefix, $path, $type = null)

    • addPrefixPaths(array $spec)

  • 校验：

    • addValidator($validator, $breakChainOnFailure = false, $options = array())

    • addValidators(array $validators)

    • setValidators(array $validators)

    • getValidator($name)

    • getValidators()

    • removeValidator($name)

    • clearValidators()

    • isValid($value, $context = null)

    • getErrors()

    • getMessages()

  • 过滤器：

    • addFilter($filter, $options = array())

    • addFilters(array $filters)

    • setFilters(array $filters)

    • getFilter($name)

    • getFilters()

    • removeFilter($name)

    • clearFilters()

  • 解析：

    • setView(Zend_View_Interface $view = null)

    • getView()

    • addDecorator($decorator, $options = null)

    • addDecorators(array $decorators)

    • setDecorators(array $decorators)

    • getDecorator($name)

    • getDecorators()

    • removeDecorator($name)

    • clearDecorators()

    • render(Zend_View_Interface $view = null)

配置

Zend_Form_Element 的构造器接受选项数组或包含选项的 Zend_Config 的对象，它也可以用 setOptions() 或 setConfig() 来配置。一般来说，命名键如下：

  • 如果 'set' + 键指向 Zend_Form_Element 方法，那么提供的值就传递给这个方法。

  • 否则，这个值就用来设置属性。

该规则的例外包括如下：

  • prefixPath 将传递给 addPrefixPaths()

  • 下面的设置器不能用这个办法：

    • setAttrib （通过 setAttribs 来工作）

    • setConfig

    • setOptions

    • setPluginLoader

    • setTranslator

    • setView

这里是一个例子，为每个配置数据类型传递配置的配置文件：

[element]
name = "foo"
value = "foobar"
label = "Foo:"
order = 10
required = true
allowEmpty = false
autoInsertNotEmptyValidator = true
description = "Foo elements are for examples"
ignore = false
attribs.id = "foo"
attribs.class = "element"
onclick = "autoComplete(this, '/form/autocomplete/element')" ; sets 'onclick' attribute
prefixPaths.decorator.prefix = "My_Decorator"
prefixPaths.decorator.path = "My/Decorator/"
disableTranslator = 0
validators.required.validator = "NotEmpty"
validators.required.breakChainOnFailure = true
validators.alpha.validator = "alpha"
validators.regex.validator = "regex"
validators.regex.options.pattern = "/^[A-F].*/$"
filters.ucase.filter = "StringToUpper"
decorators.element.decorator = "ViewHelper"
decorators.element.options.helper = "FormText"
decorators.label.decorator = "Label"

定制元素

通过继承 Zend_Form_Element 类，你可以生成自己的定制元素，这样做的原因是：

  • 共享通用的校验器和/或过滤器的元素

  • 有定制装饰器功能的元素

有两个方法一般用来扩展元素：init() 可为元素添加定制的初始化逻辑；loadDefaultDecorators() 可用于设置一个用于元素的缺省装饰器的列表。

用例子来说明，你在一个表单里生成的所有文本元素需要用 StringTrim 来过滤、用通用的规则表达式来校验，并且你想用你生成的定制的装饰器来显示它们，'My_Decorator_TextItem'。另外，你有许多想指定的标准属性，包括 'size'、 'maxLength' 和 'class'。你可以定义这样的元素如下：

<?php
class My_Element_Text extends Zend_Form_Element
{
    public function init()
    {
        $this->addPrefixPath('My_Decorator', 'My/Decorator/', 'decorator')
             ->addFilters('StringTrim')
             ->addValidator('Regex', false, array('/^[a-z0-9]{6,}$/i'))
             ->addDecorator('TextItem')
             ->setAttrib('size', 30)
             ->setAttrib('maxLength', 45)
             ->setAttrib('class', 'text');
    }
}
?>

你接着可以通知表单对象关于元素的前缀路径并开始生成元素：

<?php
$form->addPrefixPath('My_Element', 'My/Element/', 'element')
     ->addElement('foo', 'text');
?>

'foo' 元素现在是 My_Element_Text 类型并展示你描画的行为。

当继承 Zend_Form_Element 时你想 override 的另一个特殊方法是 loadDefaultDecorators()。这个方法有条件地为你的元素加载一组缺省装饰器，你可能想在你的继承类里替换你自己的装饰器。

<?php
class My_Element_Text extends Zend_Form_Element
{
    public function loadDefaultDecorators()
    {
        $this->addDecorator('ViewHelper')
             ->addDecorator('DisplayError')
             ->addDecorator('Label')
             ->addDecorator('HtmlTag', array('tag' => 'div', 'class' => 'element'));
    }
}
?>

有许多办法定制元素。别忘了阅读 Zend_Form_Element API 文档来获知所有的可用方法。

Zend_Form 快速起步
Zend_Form
Zend Framework手册 中文版
使用 Zend_Form 生成表单
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Form
  • Zend_Form
  • Zend_Form 快速起步
  • 使用 Zend_Form_Element 生成表单元素
  • 使用 Zend_Form 生成表单
  • 使用 Zend_Form_Decorator 生成定制的表单标识（Markup）
  • Zend Framework 带有的标准表单元素
  • Zend Framework 带有的标准表单装饰器（Decorators）
  • Zend_Form 的国际化
  • Zend_Form 的高级用法


使用 Zend_Form 生成表单 - Zend Framework Manual

使用 Zend_Form_Element 生成表单元素
Zend_Form
Zend Framework手册 中文版
使用 Zend_Form_Decorator 生成定制的表单标识（Markup）

使用 Zend_Form 生成表单

Zend_Form 类用来聚合表单元素，显示组和子表单。它可以在这些条目中执行下列动作：

  • 校验，包括读取错误代码和消息

  • 值聚合，包括组装（populating）条目和从所有条目读取过滤的和未过滤的值

  • 迭代所有条目，按它们键入的顺序或者从每个条目中读取的顺序提示来进行

  • 解析（rendering）整个表单，通过执行定制解析的单个装饰器（decorator）或者迭代（iterating）表单中的所有条目

虽然由 Zend_Form 生成的表单可能复杂，可能最好的用法是做简单的表单，但是对于快速程序开发和生成原型（prototyping），它是最好的。

最基本的事情是实例化一个表单对象：

<?php
// Generic form object:
$form = new Zend_Form();

// Custom form object:
$form = new My_Form()
?>

你可以可选地传递配置参数，它用来设置对象状态以及可能生成新元素：

<?php
// Passing in configuration options:
$form = new Zend_Form($config);
?>

Zend_Form 是可迭代的（iterable），它将按照它们注册的顺序和任何拥有的索引迭代所有元素、显示组和子表单。当你想手动地按适当的顺序解析（render）元素的时候，这个很有用。

Zend_Form 的魔法在于它能够为元素和显示组提供工厂服务（serve as a factory），并且通过装饰器来解析（render）自己。

插件加载器

Zend_Form 利用 Zend_Loader_PluginLoader 使开发者指定替代元素和装饰器的位置。每个表单有和它一起伴随的插件加载器，总访问器用来读取和修改每个表单。

下列加载器类型和不同的插件加载器方法 'element' 和 'decorator' 一起来使用。类型名大小写敏感。

用来和插件加载器结合使用的方法如下：

  • setPluginLoader($loader, $type): $loader 是插件加载器对象自己，type 是上述的类型之一。该方法为给定的类型设置插件加载器为新指定的加载器对象。

  • getPluginLoader($type): 按类型（$type）来获取插件加载器。

  • addPrefixPath($prefix, $path, $type = null): 添加一个 prefix/path 结合对给由 $type 指定的加载器。如果 $type 是 null，通过追加前缀给 "_Element" 和 "_Decorator"，它将尝试添加路径给所有的加载器，并用 "Element/" 和 "Decorator/" 追加路径。如果在通用的等级下有所有额外的表单元素类，这是个很方便的给它们设置基础前缀的方法。

  • addPrefixPaths(array $spec): 允许一次性添加多个路径给一个或多个插件加载器。它需要每个数组元素（item）是一个带有'path'、'prefix'和'type'键的数组。

另外，也可以用下列方法为所有通过Zend_Form实例生成元素和显示组指定前缀路径：

  • addElementPrefixPath($prefix, $path, $type = null): 就象 addPrefixPath() 一样，必需指定一个类的前缀和路径。当指定 $type，必需是由 Zend_Form_Element 指定的插件加载器类型之一，更多关于有效 $type值的信息参见 element plugins section。如果没有指定 $type，该方法假定它是一个用于所有类型的总的前缀。

  • addDisplayGroupPrefixPath($prefix, $path): 就象 addPrefixPath() 一样，必需指定一个类的前缀和路径，然而，显示组只支持装饰器作为插件，$type 不是必需的。

定制元素和装饰器是在表单和封装定制函数之间共享功能的简便方法。在元素文档（elements documentation）中参见 Custom Label example ，看定制元素如何用来替换标准类。

元素（Elements）

Zend_Form 提供了若干访问器用来从表单中添加和删除元素。这些可以获得元素对象实例或以工厂模式来为实例化元素对象自己服务。

添加元素的最基本的方法是 addElement()。该方法可以或者带有 Zend_Form_Element （或者继承 Zend_Form_Element 的类 ）类型对象的参数，或者用于建立新元素的参数 － 包括元素类型、名称和任何配置选项。

如一些例子：

<?php
// Using an element instance:
$element = new Zend_Form_Element_Text('foo');
$form->addElement($element);

// Using a factory
//
// Creates an element of type Zend_Form_Element_Text with the
// name of 'foo':
$form->addElement('text', 'foo');

// Pass label option to the element:
$form->addElement('text', 'foo', array('label' => 'Foo:'));
?>

Note: addElement() 实现 Fluent Interface
 addElement() 实现一个 fluent interface，就是说，它返回 Zend_Form 对象，而不是元素。这样做来允许你把多个 addElement()方法或者其它实现 fluent interface 的表单方法链接起来（所有 Zend_Form 中的设置器（ setters） 都实现这个模式）。
如果你想返回元素，使用 createElement()，下面是要点。然而请注意，createElement() 不把元素加到表单上。
在内部，addElement() 实际上用 createElement() 来生成元素之后把它加到表单上。

一旦元素被添加到表单，可以用名字来读取。通过使用 getElement() 方法或者通过重载（overloading）使元素作为对象属性来访问：

<?php
// getElement():
$foo = $form->getElement('foo');

// As object property:
$foo = $form->foo;
?>

偶尔地，你只想生成一个元素并不想把它加到表单上（例如，你想利用众多的用表单注册的插件路径，但稍后把这些对象加到子表单上）。createElement() 方法可以完成这些：

<?php
// $username becomes a Zend_Form_Element_Text object:
$username = $form->createElement('text', 'username');
?>

组装和读取数值

校验表单之后，你一般需要读取它的数值以便执行其它操作，如更新数据库或通知一个 web 服务。你可以通过 getValues() 来读取所有元素的值，getValue($name) 可以通过名字来读取一个单个的值：

<?php
// Get all values:
$values = $form->getValues();

// Get only 'foo' element's value:
$value = $form->getValue('foo');
?>

有时候，在解析之前，你想用特定的值来组装表单，可以通过 setDefaults() 或 populate() 方法来完成：

<?php
$form->setDefaults($data);
$form->populate($data);
?>

在另一面，你可能想在组装和校验之前清除一个表单，可使用 reset() 方法来完成：

$form->reset();

全局操作

偶尔，你想用对所有元素进行特定的操作，一般的情形包括需要为所有元素设置插件前缀路径、装饰器和过滤器，如下例：

Example #1 为所有元素设置前缀路径

可以通过类型来为所有的元素设置前缀路径，或者使用全局前缀，如这些例子：

<?php
// Set global prefix path:
// Creates paths for prefixes My_Foo_Filter, My_Foo_Validate,
// and My_Foo_Decorator
$form->addElementPrefixPath('My_Foo', 'My/Foo/');

// Just filter paths:
$form->addElementPrefixPath('My_Foo_Filter', 'My/Foo/Filter', 'filter');

// Just validator paths:
$form->addElementPrefixPath('My_Foo_Validate', 'My/Foo/Validate', 'validate');

// Just decorator paths:
$form->addElementPrefixPath('My_Foo_Decorator', 'My/Foo/Decorator', 'decorator');
?>

Example #2 为所有元素设置装饰器（Decorators）

你可以为所有元素设置装饰器。setElementDecorators() 接受一个装饰器数组， 就象 setDecorators() 一样，并对每个元素重写（overwrite）先前设置的装饰器。在本例中，我们为 ViewHelper 和一个 Label 设置装饰器：

<?php
$form->setElementDecorators(array(
    'ViewHelper',
    'Label'
));
?>

Example #3 为某些元素设置装饰器

你也可以对一个元素的子集设置装饰器，包含和排除都可以。 setElementDecorators() 的第二个参数可以是元素名数组； 缺省地，指定这样一个数组将只对这些元素设置指定的装饰器。 你也可以传递第三个参数，用来指示是包含还是排除这个元素列表的标志。 如果是 false，它将装饰 除了 这些在列表中的元素 之外 的所有元素。使用方法的标准用法，在每个元素中，任何传递的装饰器将覆盖任何先前设置的装饰器。

在下面的片段中，我们只对 'foo' 和 'bar' 元素使用视图助手和标签装饰器：

$form->setElementDecorators(
    array(
        'ViewHelper',
        'Label'
    ),
    array(
        'foo',
        'bar'
    )
);

另一方面，在这个片段中，我们对除了'foo' 元素 'bar'之外的所以元素使用视图助手和标签装饰器：

$form->setElementDecorators(
    array(
        'ViewHelper',
        'Label'
    ),
    array(
        'foo',
        'bar'
    ),
    false
);

Note: 有些装饰器不适合某些元素
虽然 setElementDecorators() 可能是个好方案，但有时候不会得到所期望的结果。例如，各种各样的按钮元素（Submit, Button, Reset）。当前使用标签（label）作为按钮（button）的值（value），并只使用 ViewHelper 和 DtDdWrapper 装饰器 －－ 防止解析另外的标签、错误、和提示，上述例子可能重复（duplicate）一些内容（标签）。
你可以使用 包含/排除 数组来克服在前面例子中所述的问题。
所以，要灵活使用这个方法，你需要排除或手工修改一些元素的装饰器来防止不希望的输出。

Example #4 为所有元素设置过滤器

大多数情况下，你想对所有元素应用同一个过滤器，一个通常的用法是 修整（trim()） 所有的值：

<?php
$form->setElementFilters(array('StringTrim'));
?>

和元素交互使用的方法

下面的方法用来和元素交互使用：

  • createElement($element, $name = null, $options = null)

  • addElement($element, $name = null, $options = null)

  • addElements(array $elements)

  • setElements(array $elements)

  • getElement($name)

  • getElements()

  • removeElement($name)

  • clearElements()

  • setDefaults(array $defaults)

  • setDefault($name, $value)

  • getValue($name)

  • getValues()

  • getUnfilteredValue($name)

  • getUnfilteredValues()

  • setElementFilters(array $filters)

  • setElementDecorators(array $decorators)

  • addElementPrefixPath($prefix, $path, $type = null)

  • addElementPrefixPaths(array $spec)

显示组（Display Groups）

显示组是生成要显示的虚拟元素组的一种方法。所有元素在表单中保持用名字可访问，但是当迭代或解析（rendering）所有表单的时候，任何在显示组中的元素将被一起解析（rendered）。最普通的用例是把（数据库表中的）字段组成一组元素。

显示组的基本类是 Zend_Form_DisplayGroup。虽然它可以直接实例化，但是一般最好是用 Zend_Form 的 addDisplayGroup() 方法来做。该方法带有一个元素数组作为第一个参数，和一个显示组的名称作为第二个参数。也可以传递一个选项数组或 Zend_Config 对象作为第三个参数。

假定元素 'username' 和 'password'已经在表单中，下面的代码将把它们组成一个 'login'显示组：

<?php
$form->addDisplayGroup(array('username', 'password'), 'login');
?>

你可以用 getDisplayGroup() 方法来访问显示组，或用显示组的名称来重载（overloading）：

<?php
// Using getDisplayGroup():
$login = $form->getDisplayGroup('login');

// Using overloading:
$login = $form->login;
?>

Note: 不需要加载缺省的装饰器
缺省地，缺省的装饰器在对象初始化过程中加载。你可以在生成显示组的时候通过传递 'disableLoadDefaultDecorators' 选项来关闭（disable）它。

<?php
$form->addDisplayGroup(
    array('foo', 'bar'),
    'foobar',
    array('disableLoadDefaultDecorators' => true)
);
该选项可以和其它选项混合，它们都是数组或者 Zend_Config 对象。

全局操作

就像对元素一样，一些操作可能影响所有的显示组，包括设置装饰器和寻找装饰器的插件路径。

Example #5 为所有的显示组设置装饰器前缀路径

缺省地，显示组继承表单所使用的任何一个装饰器的路径，然而，如果它们在另外的位置，可以使用这个方法：addDisplayGroupPrefixPath()。

<?php
$form->addDisplayGroupPrefixPath('My_Foo_Decorator', 'My/Foo/Decorator');
?>

Example #6 为所有显示组设置装饰器

你可以为所有的显示组设置装饰器。setDisplayGroupDecorators() 接受一个装饰器数组，就像 setDecorators() 一样，并将在每个显示组重写（overwrite）先前设置的装饰器。在这个例子中，我们给字段（为确保元素被迭代，FormElements 装饰器是必需的）设置装饰器：

<?php
$form->setDisplayGroupDecorators(array(
    'FormElements',
    'Fieldset'
));
?>

使用定制的显示组类

缺省地，Zend_Form 为显示组使用 Zend_Form_DisplayGroup 类，你可能需要继承这个类来提供定制的功能。addDisplayGroup() 不允许传递一个具体的实例，但确实允许用 'displayGroupClass' 键来指定一个类来作为它的一个选项：

<?php
// Use the 'My_DisplayGroup' class
$form->addDisplayGroup(
    array('username', 'password'),
    'user',
    array('displayGroupClass' => 'My_DisplayGroup')
);
?>

如果类没有加载，Zend_Form 将用 Zend_Loader 来加载。

你也可以指定一个缺省的显示组类来和表单一起使用，这样所有用这个表单对象生成的显示组将使用那个类：

<?php
// Use the 'My_DisplayGroup' class for all display groups:
$form->setDefaultDisplayGroupClass('My_DisplayGroup');
?>

这个设置可能在配置中指定为 'defaultDisplayGroupClass'，并在早期加载以确保所有的显示组使用那个类。

和显示组交互使用的方法

下列方法用来和显示组一起交互使用：

  • addDisplayGroup(array $elements, $name, $options = null)

  • addDisplayGroups(array $groups)

  • setDisplayGroups(array $groups)

  • getDisplayGroup($name)

  • getDisplayGroups()

  • removeDisplayGroup($name)

  • clearDisplayGroups()

  • setDisplayGroupDecorators(array $decorators)

  • addDisplayGroupPrefixPath($prefix, $path)

  • setDefaultDisplayGroupClass($class)

  • getDefaultDisplayGroupClass($class)

Zend_Form_DisplayGroup 方法

Zend_Form_DisplayGroup 有下列方法，以类来分组：

  • Configuration:

    • setOptions(array $options)

    • setConfig(Zend_Config $config)

  • Metadata:

    • setAttrib($key, $value)

    • addAttribs(array $attribs)

    • setAttribs(array $attribs)

    • getAttrib($key)

    • getAttribs()

    • removeAttrib($key)

    • clearAttribs()

    • setName($name)

    • getName()

    • setDescription($value)

    • getDescription()

    • setLegend($legend)

    • getLegend()

    • setOrder($order)

    • getOrder()

  • Elements:

    • createElement($type, $name, array $options = array())

    • addElement($typeOrElement, $name, array $options = array())

    • addElements(array $elements)

    • setElements(array $elements)

    • getElement($name)

    • getElements()

    • removeElement($name)

    • clearElements()

  • Plugin loaders:

    • setPluginLoader(Zend_Loader_PluginLoader $loader)

    • getPluginLoader()

    • addPrefixPath($prefix, $path)

    • addPrefixPaths(array $spec)

  • Decorators:

    • addDecorator($decorator, $options = null)

    • addDecorators(array $decorators)

    • setDecorators(array $decorators)

    • getDecorator($name)

    • getDecorators()

    • removeDecorator($name)

    • clearDecorators()

  • Rendering:

    • setView(Zend_View_Interface $view = null)

    • getView()

    • render(Zend_View_Interface $view = null)

  • I18n:

    • setTranslator(Zend_Translate_Adapter $translator = null)

    • getTranslator()

    • setDisableTranslator($flag)

    • translatorIsDisabled()

子表单

子表单服务于如干目的：

  • 生成逻辑元素组。因为子表单只是个表单，你可以把它当作独立的实体来校验。

  • 生成多页表单。因为子表单只是个表单，你可以在每页上显示一个子表单，建立每个子表单都有自己的校验逻辑的多页表单。只有一旦所有的子表单校验了，整个表单才算完整。

  • 成组地显示。像显示组一样，当子表单作为大表单的一部分解析，可以被用做组元素。然而要小心，主表单对象不知道子表单中的元素。

子表单可以是 Zend_Form 对象，或者更一般地是 Zend_Form_SubForm 对象。后者包含适合包含在大表单（例如，它不解析另外的 HTML 表单标签，但解析组元素）里的装饰器。为了加上子表单，简单地把它添加到一个表单并给出名字：

<?php
$form->addSubForm($subForm, 'subform');
?>

可以用 getSubForm($name) 或用子表单名重载（overloading）它来读取子表单：

<?php
// Using getSubForm():
$subForm = $form->getSubForm('subform');

// Using overloading:
$subForm = $form->subform;
?>

虽然子表单包含的元素不包含在表单迭代中，但子表单包含在其中。

全局操作

像元素和显示组一样，有些操作可以影响所有的子表单。然而不像显示组和元素，子表单从主表单对象继承了最多的功能，并且唯一的需要全局执行的操作是为子表单设置装饰器，setSubFormDecorators() 方法来完成此任务。在下一个例子中，我们将为所有作为字段（为确保迭代它的元素，FormElements 装饰器是必需的）的子表单设置装饰器：

<?php
$form->setSubFormDecorators(array(
    'FormElements',
    'Fieldset'
));
?>

和子表单交互使用的方法

下列方法用来和子表单交互使用：

  • addSubForm(Zend_Form $form, $name, $order = null)

  • addSubForms(array $subForms)

  • setSubForms(array $subForms)

  • getSubForm($name)

  • getSubForms()

  • removeSubForm($name)

  • clearSubForms()

  • setSubFormDecorators(array $decorators)

元数据（Metadata）和属性（Attributes）

虽然表单的有效性基本源于它所包含的元素，但它也可以包含其它元数据，如名称（在 HTML 标记语言中经常用作唯一的 ID）、表单动作和方法、许多元素、组、它所包含的子表单和属性元数据（通常用做为表单标签自己设置 HTML 属性）。

可以使用名字访问器来设置和读取表单的名字：

<?php
// Set the name:
$form->setName('registration');

// Retrieve the name:
$name = $form->getName();
?>

为了设置动作（到表单提交的 url ）和方法（提交的方法如 'POST' 或 'GET'），使用动作和方法访问器：

<?php
// Set the action and method:
$form->setAction('/user/login')
     ->setMethod('post');
?>

你也可以指定特别使用 enctype 访问器的表单编码类型。 Zend_Form 定义了两个常量， Zend_Form::ENCTYPE_URLENCODED 和 Zend_Form::ENCTYPE_MULTIPART，分别对应值为 'application/x-www-form-urlencoded' 和 'multipart/form-data'； 然而，你可以把它设置为任意的编码类型。

<?php
// Set the action, method, and enctype:
$form->setAction('/user/login')
     ->setMethod('post')
     ->setEnctype(Zend_Form::ENCTYPE_MULTIPART);
?>

Note: 方法、动作和 enctype 只用来内部解析，不用于任何校验。

Zend_Form 实现 Countable 接口，允许把它当作参数传递给计数器（count）：

<?php
$numItems = count($form);
?>

设置任意元数据可通过属性访问器来完成。因为在 Zend_Form 中重载用于访问元素、显示组和子表单，这是唯一的访问元数据的方法。

<?php
// Setting attributes:
$form->setAttrib('class', 'zend-form')
     ->addAttribs(array(
         'id'       => 'registration',
         'onSubmit' => 'validate(this)',
     ));

// Retrieving attributes:
$class = $form->getAttrib('class');
$attribs = $form->getAttribs();

// Remove an attribute:
$form->removeAttrib('onSubmit');

// Clear all attributes:
$form->clearAttribs();
?>

装饰器

为表单生成 markup 通常是一件耗时的任务，特别是如果打算重复使用同一个 markup 来显示校验错误、提交的值等。Zend_Form 的解决办法是 装饰器（decorators）。

Zend_Form 对象的装饰器可用来解析表单。FormElements 装饰器将迭代所有在表单中的条目 －－元素、显示组、子表单 －－并解析它们和返回结果。另外，装饰器可以用来封装内容、或追加、或预先准备它。

Zend_Form 的缺省装饰器是 FormElements，HtmlTag（ 封装在定义列表 ）和 Form，生成它们的等同的代码如下：

<?php
$form->setDecorators(array(
    'FormElements',
    array('HtmlTag', array('tag' => 'dl')),
    'Form'
));
?>

生成输出如下：

<form action="/form/action" method="post">
<dl>
...
</dl>
</form>

在表单对象中的任何属性设置将用做 <form> 标签的 HTML 属性。

Note: 不需要加载缺省的装饰器
缺省地，缺省的装饰器在对象初始化过程中加载。可通过传递 'disableLoadDefaultDecorators' 选项给构造器来关闭（disable）它：

<?php
$form = new Zend_Form(array('disableLoadDefaultDecorators' => true));
该选项可以和其它任何选项混合，它们都是数组或在一个 Zend_Config 对象里。

Note: 使用同类型的多个装饰器
在内部，当读取装饰器时，Zend_Form 使用装饰器的类做为查找机制。结果，可以注册同类型的多个装饰器，后来的装饰器将重些以前的（装饰器）。
To get around this,可以使用别名。不用传递装饰器或装饰器名称为第一个参数给 addDecorator()，而是传递一个带有单个元素的、带有指向装饰器对象或名字的别名的数组：

<?php
// Alias to 'FooBar':
$form->addDecorator(array('FooBar' => 'HtmlTag'), array('tag' => 'div'));

// And retrieve later:
$form = $element->getDecorator('FooBar');
?>
在 addDecorators() 和 setDecorators() 方法中，需要传递在表示装饰器的数组中的 'decorator' 选项：
<?php
// Add two 'HtmlTag' decorators, aliasing one to 'FooBar':
$form->addDecorators(
    array('HtmlTag', array('tag' => 'div')),
    array(
        'decorator' => array('FooBar' => 'HtmlTag'),
        'options' => array('tag' => 'dd')
    ),
);

// And retrieve later:
$htmlTag = $form->getDecorator('HtmlTag');
$fooBar  = $form->getDecorator('FooBar');
?>

为生成表单，你可以生成自己的装饰器。一个通常的用例是如果你知道额外的你想用的 HTML，你的装饰器可以潜在地使用从独立的元素或显示组来的装饰器生成额外的 HTML 并返回它。

下列方法可以用来和装饰器交互使用：

  • addDecorator($decorator, $options = null)

  • addDecorators(array $decorators)

  • setDecorators(array $decorators)

  • getDecorator($name)

  • getDecorators()

  • removeDecorator($name)

  • clearDecorators()

校验

表单的一个基本用例是校验提交的数据。Zend_Form 让你一次性校验整个表单或部分表单，还有对 XmlHttpRequests (AJAX)的自动校验响应。如果提交的数据无效，它有一些方法用来为元素和子表单校验失败而读取各种各样的错误代码和消息。

为了校验整个表单，使用 isValid() 方法：

<?php
if (!$form->isValid($_POST)) {
    // failed validation
}
?>

isValid() 校验每个必需的元素和任何包括在提交的数据中的非必需的元素。

有时候你可能只需要校验数据的一个子集，可以使用 isValidPartial($data)：

<?php
if (!$form->isValidPartial($data)) {
    // failed validation
}
?>

isValidPartial() 只尝试校验那些数据中匹配的元素，如果某个元素不在数据中，那就跳过。

当为 AJAX 请求校验元素或元素组，你一般要校验表单的一个子集，并想要响应返回到 JSON。用 processAjax() 正好：

<?php
$json = $form->processAjax($data);
?>

你可以发送 JSON 响应到客户端。如果表单有效，这将是个布尔 true 响应，如果表单无效，则是个包含 key/message 对的 javascript 对象，这里，每个 'message' 是校验错误消息的数组。

对于校验失败的表单，你可以分别使用 getErrors() 和 getMessages() 获取错误代码和错误消息：

<?php
$codes = $form->getErrors();
$messages = $form->getMessage();
?>

Note: 因为由 getMessages() 返回的消息是 error code/message 对的数组，一般不需要 getErrors()。

你可以通过传递元素名为单个元素来获取代码和错误消息；

<?php
$codes = $form->getErrors('username');
$messages = $form->getMessages('username');
?>

Note: 注意：当校验元素时，Zend_Form 发送第二个参数给每个元素的 isValid() 方法：被校验的数据的数组。当确定数据和合法性时，单个的校验器可以用这个来让它们来利用其它提交的值。一个典型的例子是注册表单，密码和密码确认都是必需的；密码元素可以使用密码确认做为它的校验的一部分。

定制错误消息

有时，你想定制一条或多条特定的错误消息来替代由附加到元素上的校验器所带的错误消息。 另外，有时候你想自己标记表单无效，从 1.6.0 版开始，通过下列方法来实现这个功能。

  • addErrorMessage($message): 添加一条来显示当校验失败时的错误消息。 可以多次调用，新消息就追加到堆栈。

  • addErrorMessages(array $messages): 添加多条错误消息来显示校验错误。

  • setErrorMessages(array $messages): 添加多条错误消息来显示校验错误，并覆盖先前的错误消息。

  • getErrorMessages(): 读取已定义的定制的错误消息列表。

  • clearErrorMessages(): 删除已定义的定制的错误消息。

  • markAsError(): 标记表单已经有失败的校验。

  • addError($message): 添加一条消息给定制错误消息栈并标记表单无效。

  • addErrors(array $messages): 添加数条消息给定制错误消息栈并标记表单无效。

  • setErrors(array $messages): 覆盖定制的错误消息堆栈并标记表单无效。

所有用这个方式设置的错误可以被翻译。 另外，你可以插入占位符 "%value%" 来表示元素的值；当读取到错误消息时，这个当前元素值将被替换。

方法

下面是 Zend_Form 的方法大全，按类分组：

  • 配置和选项：

    • setOptions(array $options)

    • setConfig(Zend_Config $config)

  • 插件加载器和路径：

    • setPluginLoader(Zend_Loader_PluginLoader_Interface $loader, $type = null)

    • getPluginLoader($type = null)

    • addPrefixPath($prefix, $path, $type = null)

    • addPrefixPaths(array $spec)

    • addElementPrefixPath($prefix, $path, $type = null)

    • addElementPrefixPaths(array $spec)

    • addDisplayGroupPrefixPath($prefix, $path)

  • 元数据:

    • setAttrib($key, $value)

    • addAttribs(array $attribs)

    • setAttribs(array $attribs)

    • getAttrib($key)

    • getAttribs()

    • removeAttrib($key)

    • clearAttribs()

    • setAction($action)

    • getAction()

    • setMethod($method)

    • getMethod()

    • setName($name)

    • getName()

  • 元素：

    • addElement($element, $name = null, $options = null)

    • addElements(array $elements)

    • setElements(array $elements)

    • getElement($name)

    • getElements()

    • removeElement($name)

    • clearElements()

    • setDefaults(array $defaults)

    • setDefault($name, $value)

    • getValue($name)

    • getValues()

    • getUnfilteredValue($name)

    • getUnfilteredValues()

    • setElementFilters(array $filters)

    • setElementDecorators(array $decorators)

  • 子表单：

    • addSubForm(Zend_Form $form, $name, $order = null)

    • addSubForms(array $subForms)

    • setSubForms(array $subForms)

    • getSubForm($name)

    • getSubForms()

    • removeSubForm($name)

    • clearSubForms()

    • setSubFormDecorators(array $decorators)

  • 显示组：

    • addDisplayGroup(array $elements, $name, $options = null)

    • addDisplayGroups(array $groups)

    • setDisplayGroups(array $groups)

    • getDisplayGroup($name)

    • getDisplayGroups()

    • removeDisplayGroup($name)

    • clearDisplayGroups()

    • setDisplayGroupDecorators(array $decorators)

  • 校验

    • populate(array $values)

    • isValid(array $data)

    • isValidPartial(array $data)

    • processAjax(array $data)

    • persistData()

    • getErrors($name = null)

    • getMessages($name = null)

  • 解析：

    • setView(Zend_View_Interface $view = null)

    • getView()

    • addDecorator($decorator, $options = null)

    • addDecorators(array $decorators)

    • setDecorators(array $decorators)

    • getDecorator($name)

    • getDecorators()

    • removeDecorator($name)

    • clearDecorators()

    • render(Zend_View_Interface $view = null)

  • I18n:

    • setTranslator(Zend_Translate_Adapter $translator = null)

    • getTranslator()

    • setDisableTranslator($flag)

    • translatorIsDisabled()

配置

Zend_Form 可以通过 setOptions() 和 setConfig() （或者通过传递选项或 Zend_Config 对象 ） 进行全面配置。使用这些方法，你可以指定表单元素、显示组、装饰器和元数据。

作为通用的规则，如果 'set' + 选项键涉及 Zend_Form 方法，那么提供的值将传递给那个方法。 如果访问器不存在，键被假定引用一个属性并将传递给 setAttrib() 。

规则的异常包括下列这些：

  • prefixPaths 将传递给 addPrefixPaths()

  • elementPrefixPaths 将传递给 addElementPrefixPaths()

  • displayGroupPrefixPaths 将传递给 addDisplayGroupPrefixPaths()

  • 下列设置器不能用这个方法设置：

    • setAttrib (though setAttribs *will* work)

    • setConfig

    • setDefault

    • setOptions

    • setPluginLoader

    • setSubForms

    • setTranslator

    • setView

作为一个例子，这里是一个为每个可配置数据传递配置的配置文件：

[element]
name = "registration"
action = "/user/register"
method = "post"
attribs.class = "zend_form"
attribs.onclick = "validate(this)"

disableTranslator = 0

prefixPath.element.prefix = "My_Element"
prefixPath.element.path = "My/Element/"
elementPrefixPath.validate.prefix = "My_Validate"
elementPrefixPath.validate.path = "My/Validate/"
displayGroupPrefixPath.prefix = "My_Group"
displayGroupPrefixPath.path = "My/Group/"

elements.username.type = "text"
elements.username.options.label = "Username"
elements.username.options.validators.alpha.validator = "Alpha"
elements.username.options.filters.lcase = "StringToLower"
; more elements, of course...

elementFilters.trim = "StringTrim"
;elementDecorators.trim = "StringTrim"

displayGroups.login.elements.username = "username"
displayGroups.login.elements.password = "password"
displayGroupDecorators.elements.decorator = "FormElements"
displayGroupDecorators.fieldset.decorator = "Fieldset"

decorators.elements.decorator = "FormElements"
decorators.fieldset.decorator = "FieldSet"
decorators.fieldset.decorator.options.class = "zend_form"
decorators.form.decorator = "Form"
?>

上述可以很容易被抽象成 XML 或 PHP 基于数组的配置文件。

定制表单

一个使用基于配置的表单的替代方法是继承 Zend_Form 类，有若干优点：

  • 可以容易进行单元测试来确保校验和解析如愿执行。

  • 精细地控制每个元素。

  • 重使用表单对象，最大化可移植性（不需要跟踪配置文件）。

  • 实现定制功能。

最典型的用例是使用 init() 方法来设置指定的表单元素和配置：

<?php
class My_Form_Login extends Zend_Form
{
    public function init()
    {
        $username = new Zend_Form_Element_Text('username');
        $username->class = 'formtext';
        $username->setLabel('Username:')
                 ->setDecorators(array(
                     array('ViewHelper', array('helper' => 'formText')),
                     array('Label', array('class' => 'label'))
                 ));

        $password = new Zend_Form_Element_Password('password');
        $password->class = 'formtext';
        $password->setLabel('Username:')
                 ->setDecorators(array(
                     array('ViewHelper', array('helper' => 'formPassword')),
                     array('Label', array('class' => 'label'))
                 ));

        $submit = new Zend_Form_Element_Submit('login');
        $submit->class = 'formsubmit';
        $submit->setValue('Login')
               ->setDecorators(array(
                   array('ViewHelper', array('helper' => 'formSubmit'))
               ));

        $this->addElements(array(
            $username,
            $password,
            $submit
        ));

        $this->setDecorators(array(
            'FormElements',
            'Fieldset',
            'Form'
        ));
    }
}
?>

这个表单可以简单地实例化：

<?php
$form = new My_Form_Login();
?>

所有的功能已经设置并准备好了，不需要配置文件。（注意这个例子非常简化，因为它没有为元素包含校验器和过滤器。）

另一个普通的扩展原因是定义一组缺省的装饰器，可以通过覆盖（overriding）loadDefaultDecorators() 方法来完成：

<?php
class My_Form_Login extends Zend_Form
{
    public function loadDefaultDecorators()
    {
        $this->setDecorators(array(
            'FormElements',
            'Fieldset',
            'Form'
        ));
    }
}
使用 Zend_Form_Element 生成表单元素
Zend_Form
Zend Framework手册 中文版
使用 Zend_Form_Decorator 生成定制的表单标识（Markup）
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Form
  • Zend_Form
  • Zend_Form 快速起步
  • 使用 Zend_Form_Element 生成表单元素
  • 使用 Zend_Form 生成表单
  • 使用 Zend_Form_Decorator 生成定制的表单标识（Markup）
  • Zend Framework 带有的标准表单元素
  • Zend Framework 带有的标准表单装饰器（Decorators）
  • Zend_Form 的国际化
  • Zend_Form 的高级用法


使用 Zend_Form_Decorator 生成定制的表单标识（Markup） - Zend Framework Manual

使用 Zend_Form 生成表单
Zend_Form
Zend Framework手册 中文版
Zend Framework 带有的标准表单元素

使用 Zend_Form_Decorator 生成定制的表单标识（Markup）

解析一个表单对象完全是可选的 －－ 你根本不需要使用 Zend_Form 的 render() 方法。然而，如果你用了，装饰器就用来解析各种各样的表单对象。

每个条目（元素、显示组、子表单或表单对象自己）可能附有任意数量的装饰器，然而，只有一个给定类型的装饰器可能附加给每个条目。装饰器按照注册的顺序被调用。依靠装饰器，它替换传递给它的内容，或追加或预先准备内容。

对象状态通过传递给构造器或构造器的 setOptions() 方法的配置选项来设置。当通过条目的 addDecorator() 或相关方法生成装饰器时，选项可以作为参数传递给方法。这些可用来指定 placement、在传递进的内容和新生成的内容之间的分隔符、和装饰器支持的选项。

在每个装饰器的 render() 方法被调用之前，当前条目用 setElement() 设置到装饰器，让装饰器知道条目要被解析。这让你生成只解析条目的特定部分的装饰器 －－ 例如标签（label）、值（value）、错误消息等。通过把若干个解析特定元素部分的装饰器放到一起，你可以构建复杂的表示整个条目的标识（markup）。

操作

要配置装饰器，传递选项数组或 Zend_Config 对象给它的构造器、 传递 setOptions() 的数组参数或 Zend_Config 对象给 setConfig() 。

标准选项包括：

  • placement: 布置（placement）可以是 'append' 或 'prepend' （大小写敏感），并指示传递给 render() 的内容是否分别被追加或预先准备。在装饰器替换内容的情况下，忽略这个设置。缺省设置为追加（append）。

  • separator: 用于传递给 render() 的内容和有装饰器生成的新内容之间的分隔符，或用于由装饰器（例如，FormElements 使用每个被解析的条目之间的分隔符）解析的条目之间的分隔符。在装饰器替换内容的情况下，忽略这个设置。缺省设置为 PHP_EOL。

装饰器接口指定和选项交互使用的方法，包括：

  • setOption($key, $value): 设置一个单个选项。

  • getOption($key): 读取一个单个选项值。

  • getOptions(): 读取所有选项。

  • removeOption($key): 删除一个单个选项。

  • clearOptions(): 删除所有选项。

装饰器和各种 Zend_Form 类来交互使用：Zend_Form、Zend_Form_Element、Zend_Form_DisplayGroup 和它们派生的类。 setElement() 方法让你设置当前和装饰器一起工作的对象，而 getElement() 用于读取它。

每个装饰器的 render() 方法接受字符串 $content 。当调用第一个装饰器，这个字符串一般是空的，在随后的调用中，它就被放上内容。基于装饰器的类型和传递进的选项，装饰器将替换、预先准备或追加这个字符串，一个可选的分隔符将用于后两者。

标准装饰器

Zend_Form 带有许多标准装饰器，参见 标准装饰器一章 有更多细节。

定制装饰器

如果你觉得你的解析很复杂或需要大量定制，可以考虑构造一个定制的装饰器。

装饰器只需要实现 Zend_Form_Decorator_Interface。接口说明如下：

<?php
interface Zend_Form_Decorator_Interface
{
    public function __construct($options = null);
    public function setElement($element);
    public function getElement();
    public function setOptions(array $options);
    public function setConfig(Zend_Config $config);
    public function setOption($key, $value);
    public function getOption($key);
    public function getOptions();
    public function removeOption($key);
    public function clearOptions();
    public function render($content);
}
?>

要简化这个，可以继承 Zend_Form_Decorator_Abstract，它实现了除 render() 之外的所有方法。

例如，你想减少装饰器的数量，构造一个在 HTML div 中的 "composite" 装饰器来处理标签（label）、元素、任何错误消息和描述的解析。你可以构造如下例的一个 'Composite' 装饰器：

<?php
class My_Decorator_Composite extends Zend_Form_Decorator_Abstract
{
    public function buildLabel()
    {
        $element = $this->getElement();
        $label = $element->getLabel();
        if ($translator = $element->getTranslator()) {
            $label = $translator->translate($label);
        }
        if ($element->isRequired()) {
            $label .= '*';
        }
        $label .= ':';
        return $element->getView()->formLabel($element->getName(), $label);
    }

    public function buildInput()
    {
        $element = $this->getElement();
        $helper  = $element->helper;
        return $element->getView()->$helper(
            $element->getName(),
            $element->getValue(),
            $element->getAttribs(),
            $element->options
        );
    }

    public function buildErrors()
    {
        $element  = $this->getElement();
        $messages = $element->getMessages();
        if (empty($messages)) {
            return '';
        }
        return '<div class="errors">' . $element->getView()->formErrors($messages) . '</div>';
    }

    public function buildDescription()
    {
        $element = $this->getElement();
        $desc    = $element->getDescription();
        if (empty($desc)) {
            return '';
        }
        return '<div class="description">' . $desc . '</div>';
    }

    public function render($content)
    {
        $element = $this->getElement();
        if (!$element instanceof Zend_Form_Element) {
            return $content;
        }
        if (null === $element->getView()) {
            return $content;
        }

        $separator = $this->getSeparator();
        $placement = $this->getPlacement();
        $label     = $this->buildLabel();
        $input     = $this->buildInput();
        $errors    = $this->buildErrors();
        $desc      = $this->buildDescription();

        $output = '<div class="form element">'
                . $label
                . $input
                . $errors
                . $desc
                . '</div>'

        switch ($placement) {
            case (self::PREPEND):
                return $output . $separator . $content;
            case (self::APPEND):
            default:
                return $content . $separator . $output;
        }
    }
}
?>

接着把它放到装饰器路径里：

<?php
// for an element:
$element->addPrefixPath('My_Decorator', 'My/Decorator/', 'decorator');

// for all elements:
$form->addElementPrefixPath('My_Decorator', 'My/Decorator/', 'decorator');
?>

然后指定这个装饰器为 'Composite' 并附加到一个元素：

<?php
// Overwrite existing decorators with this single one:
$element->setDecorators(array('Composite'));
?>

虽然这个例子示范了如何生成从若干元素的属性解析复杂输出装饰器，你也可以生成元素的一个单方面的装饰器，'Decorator' 和 'Label' 装饰器是这个练习的优秀示范。这样做让你混合和匹配装饰器来完成复杂输出 －－ 并且也覆盖（override）装饰器的单个方面来符合你的需求。

例如，如果你想在校验元素时显示发生的错误，但不想显示每个独立的校验错误消息，可以生成 'Errors' 装饰器：

<?php
class My_Decorator_Errors
{
    public function render($content = '')
    {
        $output = '<div class="errors">The value you provided was invalid;
            please try again</div>';

        $placement = $this->getPlacement();
        $separator = $this->getSeparator();

        switch ($placement) {
            case 'PREPEND':
                return $output . $separator . $content;
            case 'APPEND':
            default:
                return $content . $separator . $output;
        }
    }
}
?>

在这个特定的例子中，因为装饰器的最后一节，'Errors'，匹配 Zend_Form_Decorator_Errors，它将 代替 那个装饰器被解析 －－ 你不需要修改任何装饰器来修改输出。通过在已存在的标准装饰器之后命名你的装饰器，你可以不需要修改元素的装饰器来修改装饰。

使用 Zend_Form 生成表单
Zend_Form
Zend Framework手册 中文版
Zend Framework 带有的标准表单元素
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Form
  • Zend_Form
  • Zend_Form 快速起步
  • 使用 Zend_Form_Element 生成表单元素
  • 使用 Zend_Form 生成表单
  • 使用 Zend_Form_Decorator 生成定制的表单标识（Markup）
  • Zend Framework 带有的标准表单元素
  • Zend Framework 带有的标准表单装饰器（Decorators）
  • Zend_Form 的国际化
  • Zend_Form 的高级用法


Zend Framework 带有的标准表单元素 - Zend Framework Manual

使用 Zend_Form_Decorator 生成定制的表单标识（Markup）
Zend_Form
Zend Framework手册 中文版
Zend Framework 带有的标准表单装饰器（Decorators）

Zend Framework 带有的标准表单元素

Zend Framework 带有的具体元素类涵盖了大部分的 HTML 表单元素。其中大部分当装饰元素时，指定了特定的视图助手来用，但有一些还提供了另外的功能。下面是这些类的列表，还有它们提供的功能的描述。

Zend_Form_Element_Button

用来生成 HTML 按钮元素， Zend_Form_Element_Button 继承 Zend_Form_Element_Submit，并派生它的定制功能。它为装饰指定 'formButton' 视图助手。

像提交元素一样，它使用元素的标签作为元素的值来显示，还句话说，通过设置元素的值来设置按钮上的文字。如果有翻译适配器，标签将显示翻译后的文字。

因为标签用作元素的一部分，但按钮元素只用 ViewHelper 和 DtDdWrapper 装饰器。

在组装和校验表单之后，我们可用 isChecked() 方法来检查是否给定的按钮被点击。

Zend_Form_Element_Checkbox

HTML checkboxes 让你返回一个特定的值，但基本上以布尔来操作：当它被 check，值就被提交；当没有 check，什么都不提交。在内部，Zend_Form_Element_Checkbox 强制这个状态。

缺省地，已选的值是 '1'，未选的值是 '0'。你可以通过 setCheckedValue() 和 setUncheckedValue() 访问器分别来指定使用的值。在内部，任何时候你设置这个值，如果提供的值和已选的值匹配，那就是设置了，但是任何其它的值都可以使未选的值设置了。

另外，设置 checkbox 的 checked 属性的值。你可以用 isChecked() 或 访问这个属性来查询它。使用 setChecked($flag) 方法将设置标志的状态和元素中合适的已选的和未选的值。当设置 checkbox 元素的已选的状态请使用这个方法以确保设置合适的值。

Zend_Form_Element_Checkbox 使用 'formCheckbox' 视图助手。已选的值总用来组装它。

Zend_Form_Element_Hidden

隐藏元素的数据只提交，用户不用处理。 Zend_Form_Element_Hidden 使用 'formHidden' 视图助手来完成它。

Zend_Form_Element_Hash

该元素提供保护以防止 CSRF 攻击表单，确保提交的数据来自于用户的会话，而不是流氓脚本。保护是通过添加一个哈希（hash）元素给表单并在表单提交时校验它来达成的。

哈希（hash）元素名是唯一的。建议使用 salt 选项，两个哈希有相同的名字和不同的 salt 会有冲突的：

<?php
$form->addElement('hash', 'no_csrf_foo', array('salt' => 'unique'));
?>

你可以稍后使用 setSalt($salt) 方法设置 salt。

在内部，元素用 Zend_Session_Namespace 存储一个独一无二的识别符，并在提交的时候检查它（检查 TTL 没有过期）。'Identical' 校验器用于确保提交和哈希和存储的哈希匹配。

'formHidden' 视图助手用来解析在表单中的元素。

Zend_Form_Element_Image

图像也可以用作表单元素，并允许你指定图形元素作为表单按钮。

图像需要图像源文件。Zend_Form_Element_Image 让你用 setImage() 指定它（或 'image' 配置键）。当提交图像时，你也可以用 setImageValue() 访问器（或 'imageValue' 配置键）可选地指定一个值给它来用。当元素值匹配 imageValue 时，访问器 isChecked() 返回 true。

图像元素使用 图像装饰器 来解析 （还有标准错误、 HtmlTag 和 Label 装饰器）。你可以可选地指定一个标签（tag）给 图像 装饰器，它将封装图像元素。

Zend_Form_Element_MultiCheckbox

你经常会有一组相关的 checkboxes，并且想把结果组成组，这个很像 Multiselect，但是这个不是下拉列表，而是需要显示 checkbox/值对。

Zend_Form_Element_MultiCheckbox makes this a snap。像其它继承基础多重元素的元素，你可以指定一个选项列表，并很容易依靠这个列表来校验。'formMultiCheckbox' 视图助手确保这些在表单提交后返回数组。

你可以用下列方法操作各种 checkbox 选项：

  • addMultiOption($option, $value)

  • addMultiOptions(array $options)

  • setMultiOptions(array $options) （重写已存在的选项）

  • getMultiOption($option)

  • getMultiOptions()

  • removeMultiOption($option)

  • clearMultiOptions()

为了标记选中的条目，需要传递一个数组给 setValue() 。下面代码片段将检查 "bar" 和 "bat":

$element = new Zend_Form_Element_MultiCheckbox('foo', array(
    'multiOptions' => array(
        'foo' => 'Foo Option',
        'bar' => 'Bar Option',
        'baz' => 'Baz Option',
        'bat' => 'Bat Option',
    );
));

$element->setValue(array('bar', 'bat'));

注意即使是设置一个单个的值，也必需传递一个数组。

Zend_Form_Element_Multiselect

XHTML select 元素允许一个 'multiple' 属性，表明可以提交多重选项，而不是一个。Zend_Form_Element_Multiselect 继承 Zend_Form_Element_Select 并设置 multiple 属性为 'multiple' 。像其它从 Zend_Form_Element_Multi 基础类继承的类一样，你可以使用下列函数来处理选项的选择：

  • addMultiOption($option, $value)

  • addMultiOptions(array $options)

  • setMultiOptions(array $options) （重写已存在的选项）

  • getMultiOption($option)

  • getMultiOptions()

  • removeMultiOption($option)

  • clearMultiOptions()

如果翻译适配器随表单和/或元素注册，选项值将被翻译用于显示。

Zend_Form_Element_Password

密码元素基本上是普通的文本元素 －－ 除了你不想它以错误消息的形式显示或重新显示表单的时候显示出来。

Zend_Form_Element_Password 在每个校验器（确保密码在校验器错误消息上是不透明的）通过调用 setObscureValue(true) 和使用 'formPassword' 视图助手（它不显示传递给它的值）来完成它。

Zend_Form_Element_Radio

Radio 元素让你指定若干选项，而你只需要一个返回值。Zend_Form_Element_Radio 继承基础类 Zend_Form_Element_Multi，让你指定若干选项并使用 formRadio 视图助手来显示。

像其它所有继承多重元素基础类的元素，下列方法可用来处理 radio 选项的显示：

  • addMultiOption($option, $value)

  • addMultiOptions(array $options)

  • setMultiOptions(array $options) （重写已存在的选项）

  • getMultiOption($option)

  • getMultiOptions()

  • removeMultiOption($option)

  • clearMultiOptions()

Zend_Form_Element_Reset

Reset 按钮一般用于清理表单，而不是要提交的数据。然而，因为它们用于显示，所以它们属于标准元素。

Zend_Form_Element_Reset 继承 Zend_Form_Element_Submit。这样，标签（label）用于按钮显示，如果有翻译适配器，显示的内容就被翻译。它只使用 'ViewHelper' 和 'DtDdWrapper'装饰器，因为绝对不会有错误消息，也不会有标签（label）。

Zend_Form_Element_Select

Select boxes 是限定从给定数据里选择的一个通用的办法。Zend_Form_Element_Select 让你迅速简便地完成它。

因为它继承基础多重元素，下列方法可用来处理选择选项：

  • addMultiOption($option, $value)

  • addMultiOptions(array $options)

  • setMultiOptions(array $options) (overwrites existing options)

  • getMultiOption($option)

  • getMultiOptions()

  • removeMultiOption($option)

  • clearMultiOptions()

Zend_Form_Element_Select 使用 'formSelect' 视图助手来装饰。

Zend_Form_Element_Submit

提交按钮用于提交表单。你可以使用多个提交按钮，你可以使用按钮提交表单来决定哪个动作处理提交的数据。Zend_Form_Element_Submit 通过添加 isChecked()方法使决定变得容易。因为只有一个按钮由表单来提交，在处理和校验表单之后，你可以在每个提交按钮上调用这个方法来确定使用了哪个。

Zend_Form_Element_Submit 使用标签作为提交按钮的 "value"，如果有翻译适配器就翻译它。isChecked() 为了确定是否使用了该按钮，依靠标签（label）来检查提交的值。

ViewHelper 和 DtDdWrapper 装饰器解析元素。没有使用标签（label）装饰器，因为当解析元素时使用了按钮标签，一般地，对于提交元素不需要错误（代码或消息）。

Zend_Form_Element_Text

到目前为止，大部分流行的表单元素是文本元素，对于有限的文本输入，对大部分数据输入来说是个理想的元素。Zend_Form_Element_Text 使用 'formText' 视图助手来显示元素。

Zend_Form_Element_Textarea

Textareas 用于大量的文本处理，对提交的文本的长度没有限制（除非你的服务器或PHP有限制）。Zend_Form_Element_Textarea 使用 'textArea' 视图助手来显示元素，值就是元素的内容。

使用 Zend_Form_Decorator 生成定制的表单标识（Markup）
Zend_Form
Zend Framework手册 中文版
Zend Framework 带有的标准表单装饰器（Decorators）
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Form
  • Zend_Form
  • Zend_Form 快速起步
  • 使用 Zend_Form_Element 生成表单元素
  • 使用 Zend_Form 生成表单
  • 使用 Zend_Form_Decorator 生成定制的表单标识（Markup）
  • Zend Framework 带有的标准表单元素
  • Zend Framework 带有的标准表单装饰器（Decorators）
  • Zend_Form 的国际化
  • Zend_Form 的高级用法


Zend Framework 带有的标准表单装饰器（Decorators） - Zend Framework Manual

Zend Framework 带有的标准表单元素
Zend_Form
Zend Framework手册 中文版
Zend_Form 的国际化

Zend Framework 带有的标准表单装饰器（Decorators）

Zend_Form 带有若干标准装饰器，更多关于装饰器的一般用法，参见 the Decorators section。

Zend_Form_Decorator_Callback

回调（callback）装饰器可以对解析内容执行任意回调。回调应当通过传递给装饰器配置的 'callback' 选项来指定，可以是任何有效的 PHP 回调类型。回调接受三个参数 $content （传递给装饰器的原始内容）、$element （被装饰的条目）和 一个 $options 数组。这是个回调的例子：

<?php
class Util
{
    public static function label($content, $element, array $options)
    {
        return '<span class="label">' . $element->getLabel() . "</span>";
    }
}
?>

这个回调被指定为 array('Util','label')，并为标签（label）产生一些（坏的） HTML markup。回调装饰器将替换追加或用这个返回值预先准备原始内容。

回调装饰器允许为替换选项指定一个 null 值，它将用回调返回值来替换原始内容，'prepend' 和 'append' 仍然有效。

Zend_Form_Decorator_Captcha

Captcha 装饰器用于 Captcha 表单元素 。 它利用 captcha 适配器的 render() 方法来生成输出。

Captcha 装饰器的一个变量，'Captcha_Word'，也常用，并生成两个元素，id 和 input。 id 表示比较依靠的会话识别符，input 用于 captcha 的校验。这些作为单个的元素被校验。

Zend_Form_Decorator_Description

描述装饰器用来显示设置在 Zend_Form、 Zend_Form_Element 或 Zend_Form_DisplayGroup 条目上的描述。它使用对象的 getDescription() 方法来取出描述。普通的用例用来为元素提供用户接口（UI）提示。

缺省地，如果没有描述，就不会生成输出。如果有描述，它将缺省地封装在 p 标签里，当生成装饰器时你可以通过传递一个 tag选项或调用 setTag() 来指定一个标签。你也可以使用 class 选项或调用 setClass() 来指定一个类，缺省使用 'hint' 类。

缺省描述使用视图对象的转义机制来转义。你可以传递 false 值给装饰器的 'escape' 选项或 setEscape() 方法来关闭（disable）它。

Zend_Form_Decorator_DtDdWrapper

缺省装饰器使用定义列表 (<dl>) 来解析表单元素。因为表单条目可以以任何顺序出现，显示组和子表单可以用其它表单条目点缀。为在定义列表里保持这些特定的题目类型，DtDdWrapper 生成一个新的、空定义 term (<dt>) 并在新定义数据（<dd>）里封装它的内容 。输出看起来是这样的：

<dt></dt>
<dd><fieldset id="subform">
    <legend>User Information</legend>
    ...
</fieldset></dd>

装饰器通过把提供给它的内容封装在 <dd> 元素里来替换它。

Zend_Form_Decorator_Errors

元素错误用错误装饰器来获得它们自己的装饰器。这个装饰器代理 FormErrors 视图助手，它在无序的列表里 (<ul>) 解析错误消息作为列表条目。<ul> 元素接收 "errors" 类。

错误装饰器可以预先准备或追加提供给它的内容。

Zend_Form_Decorator_Fieldset

显示组和子表单缺省地在字段（fieldsets）里解析内容。字段装饰器在注册的元素里检查 'legend' 选项或 getLegend() 方法，如果非空，就用它作为 legend。任何传递进来的内容被封装在 HTML 字段里，替换原先的内容。任何在装饰器条目里的属性设置都作为 HTML 属性传递给字段。

Zend_Form_Decorator_Form

Zend_Form 对象一般需要解析 HTML 表单标签（tag）。表单装饰器代理表单视图助手。它使用 Zend_Form 对象的动作和方法，封装任何提供给它的内容到 HTML 表单元素，和任何属性作为 HTML 属性。

Zend_Form_Decorator_FormElements

表单、显示组和子表单是元素的集合。为了解析这些元素，它们使用 FormElements 装饰器（它迭代所有条目，在每个条目调用 render() 并用注册的分隔符连接它们）。它可以追加或预先准备传递给它的内容。

Zend_Form_Decorator_HtmlTag

HtmlTag 装饰器让你用 HTML 标签来装饰内容。通过传递 'tag' 选项和任何其它用作 HTML 属性的选项来使用标签。标签缺省地假定为 block 一级，通过封装在给定的标签里来替换内容。然而，你也可以指定一个追加或者预先准备的替换。

Zend_Form_Decorator_Image

图像装饰器让你生成一个 HTML 图像输入（<input type="image" ... />），并在另一个 HTML 标签里可选地解析它。

缺省地，（图像）装饰器使用元素的 src 属性，它可以用 setImage() 方法来设置图像源。另外，元素的标签（label）将用做 alt 标签（tag），并且 imageValue（用图像元素的 setImageValue() 和 getImageValue() 访问器来处理）将用于值的设置。

为指定一个封装元素的 HTML 标签，或者传递 'tag' 选项给装饰器，或者显式地调用 setTag()。

Zend_Form_Decorator_Label

表单元素一般都有标签，标签装饰器用来解析这些标签。它代理 FormLabel 视图助手，用这个元素的 getLabel() 方法把元素标签读出来。如果没有标签，就不解析。缺省地，如果有翻译适配器和这个标签的翻译，标签就被翻译。

你可以可选地指定一个 'tag' 选项，如果提供了，它封装在 block 一级标签（tag）封装这个标签（label）。如果有 'tag' 选项而没有标签（label）存在，那么标签（tag）就被不带内容解析。你可以用 'class' 选项或调用 setClass() 来指定和标签（tag）一起使用的类。

另外，当显示元素（基于标签（label）是否用于可选的或必需的元素）时，你可以指定前缀和后缀来用。普通的用例是追加 ':' 给标签（label），或者一个 '*' 来表明元素是必需的。可以用下列选项和方法来做：

  • optionalPrefix: 当元素是可选的时候，设置文本给标签带有的前缀。使用 setOptionalPrefix() 和 getOptionalPrefix() 访问器来处理。

  • optionalSuffix: 当元素是可选的时候，设置追加给标签的文本。使用 setOptionalSuffix() 和 getOptionalSuffix() 访问器来处理。

  • requiredPrefix: 当元素必需的时候，设置文本给标签带有的前缀。使用 setRequiredPrefix() 和 getRequiredPrefix() 访问器来处理。

  • requiredSuffix: 当元素是必需的时候，设置追加给标签的文本。使用 setRequiredSuffix() 和 getRequiredSuffix() 访问器来处理。

缺省地，标签装饰器预先准备给要提供的内容，指定一个 'append' 的 'placement' 选项来把它放在内容的后面。

Zend_Form_Decorator_ViewHelper

大部分元素使用 Zend_View 助手来解析，这是通过 ViewHelper 装饰器来完成的。这样，你可以指定一个 'helper' 标签（tag）来显式地设置视图助手来使用。如果什么也没有提供，它使用元素类名的最后一节来确定助手，用字符串 'form'来预先准备：例如，'Zend_Form_Element_Text' 寻找一个叫 'formText' 的视图助手。

任何提供的元素的属性被当作元素属性来传递给视图助手。

缺省地，这个装饰器追加内容，使用 'placement' 选项类指定另外的布置（placement）。

Zend_Form_Decorator_ViewScript

有时候你可能想用视图脚本来生成元素，这样你可以对元素有精细的控制，把视图脚本交给（页面）设计者，或者基于你所使用的模块来构造一个简便地覆盖（override）设置的办法（每个模块可以可选地覆盖元素视图脚本来符合它们的需求）。ViewScript 装饰器解决了这个问题。

ViewScript 装饰器要求一个 'viewScript' 选项，或者提供给装饰器，或者作为元素的属性。它接着解析哪个视图脚本为部分脚本，意思是每次调用它有自己的变量范围。没有从视图来的变量将注入除非元素它自己。若干变量如下：

  • element: 被装饰的元素

  • content: 传递给装饰器的内容

  • decorator: 装饰器对象自己

  • 另外，所有通过 setOptions() 传递给装饰器的不用于内部（如 placement、 separator 等）的选项作为视图变量传递给视图脚本。

作为例子，你可以有下列元素：

<?php
// Setting the decorator for the element to a single, ViewScript, decorator,
// specifying the viewScript as an option, and some extra options:
$element->setDecorators(array(array('ViewScript', array(
    'viewScript' => '_element.phtml',
    'class'      => 'form element'
))));

// OR specifying the viewScript as an element attribute:
$element->viewScript = '_element.phtml';
$element->setDecorators(array(array('ViewScript', array('class' => 'form element'))));
?>

你可以接着有一个如下的视图脚本：

<div class="<?= $this->class ?>">
    <?= $this->formLabel($this->element->getName(), $this->element->getLabel()) ?>
    <?= $this->{$this->element->helper}(
        $this->element->getName(),
        $this->element->getValue(),
        $this->element->getAttribs()
    ) ?>
    <?= $this->formErrors($this->element->getMessages()) ?>
    <div class="hint"><?= $this->element->getDescription() ?></div>
</div>

Note: 用视图脚本替换内容
你可能发现用视图脚本来替换提供给装饰器的内容很有用 －－ 例如，如果你想封装它。你可以通过指定一个布尔 false 值给装饰器的 'placement' 选项来做：

<?php
// At decorator creation:
$element->addDecorator('ViewScript', array('placement' => false));

// Applying to an existing decorator instance:
$decorator->setOption('placement', false);

// Applying to a decorator already attached to an element:
$element->getDecorator('ViewScript')->setOption('placement', false);

// Within a view script used by a decorator:
$this->decorator->setOption('placement', false);
?>

当你想对元素的解析有个非常精细的控制，建议使用 ViewScript 装饰器。

Zend Framework 带有的标准表单元素
Zend_Form
Zend Framework手册 中文版
Zend_Form 的国际化
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Form
  • Zend_Form
  • Zend_Form 快速起步
  • 使用 Zend_Form_Element 生成表单元素
  • 使用 Zend_Form 生成表单
  • 使用 Zend_Form_Decorator 生成定制的表单标识（Markup）
  • Zend Framework 带有的标准表单元素
  • Zend Framework 带有的标准表单装饰器（Decorators）
  • Zend_Form 的国际化
  • Zend_Form 的高级用法


Zend_Form 的国际化 - Zend Framework Manual

Zend Framework 带有的标准表单装饰器（Decorators）
Zend_Form
Zend Framework手册 中文版
Zend_Form 的高级用法

Zend_Form 的国际化

开发者日益需要制作网站内容支持多种语言和地区。Zend_Form 把这样的任务变得简单并利用 Zend_Translate 和 Zend_Validate 来完成。

缺省地，Zend_Form 不支持国际化（I18n）。要打开在 Zend_Form 中的 I18n 功能，需要带适当的适配器实例化一个 Zend_Translate 对象，并把它附加到 Zend_Form 和/或 Zend_Validate 中。参见 Zend_Translate 文档 有更多关于生成翻译对象和翻译文件的信息。

Note: 可以对每个元素关闭翻译
你可以通过调用 setDisableTranslator($flag) 方法或传递 disableTranslator 选项给对象来对任何表单、元素、显示组或子表单关闭翻译。当你想有选择地对独立的元素或一组元素关闭翻译，这个很有用。

在表单中初始化 I18n

要在表单中初始化 I18n，你需要或者 Zend_Translate 对象或者 Zend_Translate_Adapter 对象，详细请见 Zend_Translate 文档。一旦你有一个翻译对象，你将有若干选项：

  • Easiest: 添加它到注册表。Zend Framework 中所有 I18n 相关的组件将自动发现一个翻译对象（这个对象在注册表中在 'Zend_Translate' 键之下）并用它翻译和/或本地化：

    <?php
// use the 'Zend_Translate' key; $translate is a Zend_Translate object:
Zend_Registry::set('Zend_Translate', $translate);
?>

    这将由 Zend_Form、Zend_Validate 和 Zend_View_Helper_Translate 来获得。

  • 如果你所担心的是翻译校验错误消息，可以用 Zend_Validate_Abstract 来注册翻译对象：

    <?php
// Tell all validation classes to use a specific translate adapter:
Zend_Validate_Abstract::setDefaultTranslator($translate);
?>

  • 另外，你可以（把它）附加到 Zend_Form 对象作为全局翻译器。这个也有翻译校验错误消息的副作用：

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

  • 最后，你可以用 setTranslator() 方法附加一个翻译器到一个特定的表单实例或特定的元素：

    <?php
// Tell *this* form instance to use a specific translate adapter; it will also
// be used to translate validation error messages for all elements:
$form->setTranslator($translate);

// Tell *this* element to use a specific translate adapter; it will also be used
// to translate validation error messages for this particular element:
$element->setTranslator($translate);
?>

标准 I18n 目标

既然你已经附加了翻译对象，那么到底什么是缺省翻译？

  • Validation error messages. 校验错误消息可以被翻译。使用从 Zend_Validate 校验类来的各种错误代码常数作为消息的 IDs。更多关于这些代码的信息，参见 Zend_Validate 文档。

    另外，到 1.6.0 版，你可使用实际的错误消息作为消息识别符来提供翻译。我们倾向在 1.6.0 版及以上使用这个办法，因为我们在将来的版本中废除消息键翻译。

  • Labels. 如果翻译存在，元素标签 （labels）将被翻译。

  • Fieldset Legends. 显示组和子表单缺省地在字段中解析。字段装饰器在解析字段钱尝试翻译 legend。

  • Form and Element Descriptions. 所有表单类型（元素、表单、显示组、子表单）允许指定一个可选的条目描述。描述装饰器可用来解析它，缺省地它将尝试翻译它。

  • Multi-option Values. 对于各种从 Zend_Form_Element_Multi 继承的条目（包括 MultiCheckbox、 Multiselect 和 Radio 元素），如果翻译可用，选项值（不是键）将被翻译。这意味着显示给用户的选项标签将被翻译。

  • Submit and Button Labels. 各种提交和按钮元素（按钮，提交和重置）将翻译显示给用户的标签。

Zend Framework 带有的标准表单装饰器（Decorators）
Zend_Form
Zend Framework手册 中文版
Zend_Form 的高级用法
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Form
  • Zend_Form
  • Zend_Form 快速起步
  • 使用 Zend_Form_Element 生成表单元素
  • 使用 Zend_Form 生成表单
  • 使用 Zend_Form_Decorator 生成定制的表单标识（Markup）
  • Zend Framework 带有的标准表单元素
  • Zend Framework 带有的标准表单装饰器（Decorators）
  • Zend_Form 的国际化
  • Zend_Form 的高级用法


Zend_Form 的高级用法 - Zend Framework Manual

Zend_Form 的国际化
Zend_Form
Zend Framework手册 中文版
Zend_Gdata

Zend_Form 的高级用法

Zend_Form 有丰富的函数，其中许多面向有经验的开发者。这一章打算用例子和用例来介绍这些函数。

数组符号（Notation）

许多有经验的 web 开发者喜欢在元素名上用数组符号把相关的表单元素组成组。例如，如果有两个地址在表单上，一个邮寄地址和一个帐单地址，你可能会有相同的元素，通过把它们用数组组成组，你可以确保它们能分别被抓取。用下面的表单做个例子：

<form>
    <fieldset>
        <legend>Shipping Address</legend>
        <dl>
            <dt><label for="recipient">Ship to:</label></dt>
            <dd><input name="recipient" type="text" value="" /></dd>

            <dt><label for="address">Address:</label></dt>
            <dd><input name="address" type="text" value="" /></dd>

            <dt><label for="municipality">City:</label></dt>
            <dd><input name="municipality" type="text" value="" /></dd>

            <dt><label for="province">State:</label></dt>
            <dd><input name="province" type="text" value="" /></dd>

            <dt><label for="postal">Postal Code:</label></dt>
            <dd><input name="postal" type="text" value="" /></dd>
        </dl>
    </fieldset>

    <fieldset>
        <legend>Billing Address</legend>
        <dl>
            <dt><label for="payer">Bill To:</label></dt>
            <dd><input name="payer" type="text" value="" /></dd>

            <dt><label for="address">Address:</label></dt>
            <dd><input name="address" type="text" value="" /></dd>

            <dt><label for="municipality">City:</label></dt>
            <dd><input name="municipality" type="text" value="" /></dd>

            <dt><label for="province">State:</label></dt>
            <dd><input name="province" type="text" value="" /></dd>

            <dt><label for="postal">Postal Code:</label></dt>
            <dd><input name="postal" type="text" value="" /></dd>
        </dl>
    </fieldset>

    <dl>
        <dt><label for="terms">I agree to the Terms of Service</label></dt>
        <dd><input name="terms" type="checkbox" value="" /></dd>

        <dt></dt>
        <dd><input name="save" type="submit" value="Save" /></dd>
    </dl>
</form>

在本例中，帐单地址和邮寄地址包含一些相同的字段，这意味着一个可能会覆盖另一个。我们可以用数组符号来解决这个问题：

<form>
    <fieldset>
        <legend>Shipping Address</legend>
        <dl>
            <dt><label for="shipping-recipient">Ship to:</label></dt>
            <dd><input name="shipping[recipient]" id="shipping-recipient"
                type="text" value="" /></dd>

            <dt><label for="shipping-address">Address:</label></dt>
            <dd><input name="shipping[address]" id="shipping-address"
                type="text" value="" /></dd>

            <dt><label for="shipping-municipality">City:</label></dt>
            <dd><input name="shipping[municipality]" id="shipping-municipality"
                type="text" value="" /></dd>

            <dt><label for="shipping-province">State:</label></dt>
            <dd><input name="shipping[province]" id="shipping-province"
                type="text" value="" /></dd>

            <dt><label for="shipping-postal">Postal Code:</label></dt>
            <dd><input name="shipping[postal]" id="shipping-postal"
                type="text" value="" /></dd>
        </dl>
    </fieldset>

    <fieldset>
        <legend>Billing Address</legend>
        <dl>
            <dt><label for="billing-payer">Bill To:</label></dt>
            <dd><input name="billing[payer]" id="billing-payer"
                type="text" value="" /></dd>

            <dt><label for="billing-address">Address:</label></dt>
            <dd><input name="billing[address]" id="billing-address"
                type="text" value="" /></dd>

            <dt><label for="billing-municipality">City:</label></dt>
            <dd><input name="billing[municipality]" id="billing-municipality"
                type="text" value="" /></dd>

            <dt><label for="billing-province">State:</label></dt>
            <dd><input name="billing[province]" id="billing-province"
                type="text" value="" /></dd>

            <dt><label for="billing-postal">Postal Code:</label></dt>
            <dd><input name="billing[postal]" id="billing-postal"
                type="text" value="" /></dd>
        </dl>
    </fieldset>

    <dl>
        <dt><label for="terms">I agree to the Terms of Service</label></dt>
        <dd><input name="terms" type="checkbox" value="" /></dd>

        <dt></dt>
        <dd><input name="save" type="submit" value="Save" /></dd>
    </dl>
</form>

在上例中，我们有了两个单独的地址。在提交的表单，我们有三个元素，'save' 元素表示提交，和两个数组 'shipping' 和 'billing'，每个都有键对应它们的元素。

Zend_Form 尝试用 sub forms 自动完成这个过程。缺省地，子表单用前面 HTML 表单列表包括 ids 所示的数组符号来解析，数组名基于子表单名，键基于包含在子表单中的元素。子表单的嵌套有任意深度，这将生成嵌套数组来反映它的结构。另外，Zend_Form 中不同的校验程序遵循数组结构，不论子表单的嵌套有多深，都确保表单校验正确。你不需要做任何事情来获得这些好处，缺省是打开（enabled）的。

另外，有工具让你有条件地打开数组符号，也可以指定特定的数组给元素和集合所属的（子表单或表单）：

  • Zend_Form::setIsArray($flag)：通过设置标志为 true，你可以让整个表单当作数组。缺省地，表单名将是数组名，除非调用了 setElementsBelongTo()。如果表单没有名称，或如果 setElementsBelongTo() 没有设置，这个标志将被忽略（因为没有数组名给元素所属于的表单）。

    你可以用 isArray() 访问器来决定一个表单是否被当作数组。

  • Zend_Form::setElementsBelongTo($array)：用这个方法，你可以指定数组名给元素所属的表单，也可以使用 getElementsBelongTo() 访问器来确定（获得？）它的名字。

另外，在元素一级，你可以用 Zend_Form_Element::setBelongsTo() 方法指定可能属于特定的数组的独立的元素。 为了找出这个值是什么 － 是否显式或隐式地通过表单 － 可以用 getBelongsTo() 访问器来做。

多页表单

目前，Zend_Form 没有正式支持多页表单，然而，可以用一些额外的工具来实现。

生成多页表单的关键是利用子表单，但每个页面只显示一个子表单。这让你一次提交一个单个的表单并校验它，直到所有表单都提交了才处理。

Example #1 注册表单示例

让我们用注册表单作为例子，我们的意图是在第一页上读取期望的用户名和密码，还有用户的元数据 －－ 用户的名字、姓和地点 －－ 最后让他们决定使用哪个邮件列表（如果有的话）。

首先，来生成表单，并在里面定义一些子表单：

<?php
class My_Form_Registration extends Zend_Form
{
    public function init()
    {
        // Create user sub form: username and password
        $user = new Zend_Form_SubForm();
        $user->addElements(array(
            new Zend_Form_Element_Text('username', array(
                'required'   => true,
                'label'      => 'Username:',
                'filters'    => array('StringTrim', 'StringToLower'),
                'validators' => array(
                    'Alnum',
                    array('Regex', false, array('/^[a-z][a-z0-9]{2,}$/'))
                )
            )),

            new Zend_Form_Element_Password('password', array(
                'required'   => true,
                'label'      => 'Password:',
                'filters'    => array('StringTrim'),
                'validators' => array(
                    'NotEmpty',
                    array('StringLength', false, array(6))
                )
            )),
        ));

        // Create demographics sub form: given name, family name, and location
        $demog = new Zend_Form_SubForm();
        $demog->addElements(array(
            new Zend_Form_Element_Text('givenName', array(
                'required'   => true,
                'label'      => 'Given (First) Name:',
                'filters'    => array('StringTrim'),
                'validators' => array(
                    array('Regex', false, array('/^[a-z][a-z0-9., \'-]{2,}$/i'))
                )
            )),

            new Zend_Form_Element_Text('familyName', array(
                'required'   => true,
                'label'      => 'Family (Last) Name:',
                'filters'    => array('StringTrim'),
                'validators' => array(
                    array('Regex', false, array('/^[a-z][a-z0-9., \'-]{2,}$/i'))
                )
            )),

            new Zend_Form_Element_Text('location', array(
                'required'   => true,
                'label'      => 'Your Location:',
                'filters'    => array('StringTrim'),
                'validators' => array(
                    array('StringLength', false, array(2))
                )
            )),
        ));

        // Create mailing lists sub form
        $listOptions = array(
            'none'        => 'No lists, please',
            'fw-general'  =>  'Zend Framework General List',
            'fw-mvc'      =>  'Zend Framework MVC List',
            'fw-auth'     =>  'Zend Framwork Authentication and ACL List',
            'fw-services' => 'Zend Framework Web Services List',
        );
        $lists = new Zend_Form_SubForm();
        $lists->addElements(array(
            new Zend_Form_Element_MultiCheckbox('subscriptions', array(
                'label'        => 'Which lists would you like to subscribe to?',
                'multiOptions' => $listOptions,
                'required'     => true,
                'filters'      => array('StringTrim'),
                'validators'   => array(
                    array('InArray', false, array(array_keys($listOptions)))
                )
            )),
        ));

        // Attach sub forms to main form
        $this->addSubForms(array(
            'user'  => $user,
            'demog' => $demog,
            'lists' => $lists
        ));
    }
}

注意还没有提交按钮，而起我们对子表单的装饰器也没有做任何事情 －－ 意思是缺省地他们作为字段（fieldsets）显示。我们将能够 override 这些因为我们显示每个独立的子表单，并加入提交按钮这样我们就可以处理它们了 －－ 也要求有动作和方法（注：这里的方法是 'post' 或 'get'）属性。来给我们的类添砖加瓦让它提供那些信息：

class My_Form_Registration extends Zend_Form
{
    // ...

    /**
     * Prepare a sub form for display
     *
     * @param  string|Zend_Form_SubForm $spec
     * @return Zend_Form_SubForm
     */
    public function prepareSubForm($spec)
    {
        if (is_string($spec)) {
            $subForm = $this->{$spec};
        } elseif ($spec instanceof Zend_Form_SubForm) {
            $subForm = $spec;
        } else {
            throw new Exception('Invalid argument passed to ' . __FUNCTION__ . '()');
        }
        $this->setSubFormDecorators($subForm)
             ->addSubmitButton($subForm)
             ->addSubFormActions($subForm);
        return $subForm;
    }

    /**
     * Add form decorators to an individual sub form
     *
     * @param  Zend_Form_SubForm $subForm
     * @return My_Form_Registration
     */
    public function setSubFormDecorators(Zend_Form_SubForm $subForm)
    {
        $subForm->setDecorators(array(
            'FormElements',
            array('HtmlTag', array('tag' => 'dl', 'class' => 'zend_form')),
            'Form',
        ));
        return $this;
    }

    /**
     * Add a submit button to an individual sub form
     *
     * @param  Zend_Form_SubForm $subForm
     * @return My_Form_Registration
     */
    public function addSubmitButton(Zend_Form_SubForm $subForm)
    {
        $subForm->addElement(new Zend_Form_Element_Submit(
            'save',
            array(
                'label'    => 'Save and continue',
                'required' => false,
                'ignore'   => true,
            )
        ));
        return $this;
    }

    /**
     * Add action and method to sub form
     *
     * @param  Zend_Form_SubForm $subForm
     * @return My_Form_Registration
     */
    public function addSubFormActions(Zend_Form_SubForm $subForm)
    {
        $subForm->setAction('/registration/process')
                ->setMethod('post');
        return $this;
    }
}

接着，我们也需要为动作控制器添加一些辅助东西，并有若干考虑。首先，我们需要确保在请求之间保持表单数据，这样可以确定何时退出。第二，我们需要一些逻辑来确定表单的哪部分已经提交，哪个子表单需要基于这些信息来显示。我们使用 Zend_Session_Namespace 来保持数据，它也会告诉我们提交哪个表单。

让我们来创建控制器，并添加用于获取表单实例的方法：

<?php
class RegistrationController extends Zend_Controller_Action
{
    protected $_form;

    public function getForm()
    {
        if (null === $this->_form) {
            require_once 'My/Form/Registration.php';
            $this->_form = new My_Form_Registration();
        }
        return $this->_form;
    }
}

现在，添加一些函数来确定显示哪个表单。基本上，直到整个表单被认为有效，我们才需要继续显示表单片段。另外，我们可能想确保它们是按一定的顺序：用户、demog 和 列表。我们在可以通过检查出现在每个子表单上的特定键的会话命名空间确定哪个数据被提交。

class RegistrationController extends Zend_Controller_Action
{
    // ...

    protected $_namespace = 'RegistrationController';
    protected $_session;

    /**
     * Get the session namespace we're using
     *
     * @return Zend_Session_Namespace
     */
    public function getSessionNamespace()
    {
        if (null === $this->_session) {
            require_once 'Zend/Session/Namespace.php';
            $this->_session = new Zend_Session_Namespace($this->_namespace);
        }

        return $this->_session;
    }

    /**
     * Get a list of forms already stored in the session
     *
     * @return array
     */
    public function getStoredForms()
    {
        $stored = array();
        foreach ($this->getSessionNamespace() as $key => $value) {
            $stored[] = $key;
        }

        return $stored;
    }

    /**
     * Get list of all subforms available
     *
     * @return array
     */
    public function getPotentialForms()
    {
        return array_keys($this->getForm()->getSubForms());
    }

    /**
     * What sub form was submitted?
     *
     * @return false|Zend_Form_SubForm
     */
    public function getCurrentSubForm()
    {
        $request = $this->getRequest();
        if (!$request->isPost()) {
            return false;
        }

        foreach ($this->getPotentialForms() as $name) {
            if ($data = $request->getPost($name, false)) {
                if (is_array($data)) {
                    return $this->getForm()->getSubForm($name);
                    break;
                }
            }
        }

        return false;
    }

    /**
     * Get the next sub form to display
     *
     * @return Zend_Form_SubForm|false
     */
    public function getNextSubForm()
    {
        $storedForms    = $this->getStoredForms();
        $potentialForms = $this->getPotentialForms();

        foreach ($potentialForms as $name) {
            if (!in_array($name, $storedForms)) {
                return $this->getForm()->getSubForm($name);
            }
        }

        return false;
    }
}

上述方法让我们使用符合如 "$subForm = $this->getCurrentSubForm();" 来读取当前子表单来校验，或者 "$next = $this->getNextSubForm();" 来获得下一个来显示。

现在，让我们看一下如何处理和显示不同的子表单。我们可以使用 getCurrentSubForm() 来确定表单是否提交（返回 false 值表示没有显示或提交），并且用 getNextSubForm() 来获取表单来显示。我们还可以用表单的 prepareSubForm() 方法来确保表单已准备好显示。

当我们收到表单提交，可以校验子表单并接着检查是否整个表单有效。为完成这些任务，我们需要另外的方法确保提交的数据添加到会话和什么时候校验整个表单，我们依靠从会话来的所有片段（segments）来校验：

<?php
class My_Form_Registration extends Zend_Form
{
    // ...

    /**
     * Is the sub form valid?
     *
     * @param  Zend_Form_SubForm $subForm
     * @param  array $data
     * @return bool
     */
    public function subFormIsValid(Zend_Form_SubForm $subForm, array $data)
    {
        $name = $subForm->getName();
        if ($subForm->isValid($data)) {
            $this->getSessionNamespace()->$name = $subForm->getValues();
            return true;
        }

        return false;
    }

    /**
     * Is the full form valid?
     *
     * @return bool
     */
    public function formIsValid()
    {
        $data = array();
        foreach ($this->getSessionNamespace() as $key => $info) {
            $data[$key] = $info;
        }

        return $this->getForm()->isValid($data);
    }
}

八字已经画了一撇，让我们来为控制器构造一个动作。我们需要为表单做一个 landing 页面，接着'process' 动作来处理表单。

<?php
class RegistrationController extends Zend_Controller_Action
{
    // ...

    public function indexAction()
    {
        // Either re-display the current page, or grab the "next" (first)
        // sub form
        if (!$form = $this->getCurrentSubForm()) {
            $form = $this->getNextSubForm();
        }
        $this->view->form = $this->getForm()->prepareSubForm($form);
    }

    public function processAction()
    {
        if (!$form = $this->getCurrentSubForm()) {
            return $this->_forward('index');
        }

        if (!$this->subFormIsValid($form, $this->getRequest()->getPost())) {
            $this->view->form = $this->getForm()->prepareSubForm($form);
            return $this->render('index');
        }

        if (!$this->formIsValid()) {
            $form = $this->getNextSubForm();
            $this->view->form = $this->getForm()->prepareSubForm($form);
            return $this->render('index');
        }

        // Valid form!
        // Render information in a verification page
        $this->view->info = $this->getSessionNamespace();
        $this->render('verification');
    }
}

正如你注意到的，处理表单的代码相当简单。我们检查是否有一个子表单提交，如果没有，就回到 landing 页面。如果我们确实有一个子表单，就尝试校验它，如果失败，重新显示。如果子表单有效，那么我们就检查表单是否有效，它将指示我们是否完成，如果没有，我们就显示下一个表单片段。最后，我们显示一个确认过的带有会话内容的页面。

The view scripts are very simple:

<? // registration/index.phtml ?>
<h2>Registration</h2>
<?= $this->form ?>

<? // registration/verification.phtml ?>
<h2>Thank you for registering!</h2>
<p>
    这里是你所提供的信息：
</p>

<?
// Have to do this construct due to how items are stored in session namespaces
foreach ($this->info as $info):
    foreach ($info as $form => $data): ?>
<h4><?= ucfirst($form) ?>:</h4>
<dl>
    <? foreach ($data as $key => $value): ?>
    <dt><?= ucfirst($key) ?></dt>
    <? if (is_array($value)):
        foreach ($value as $label => $val): ?>
    <dd><?= $val ?></dd>
        <? endforeach;
       else: ?>
    <dd><?= $this->escape($value) ?></dd>
    <? endif;
    endforeach; ?>
</dl>
<? endforeach;
endforeach ?>

Zend Framework 的下次发行将通过抽象会话和顺序逻辑来提供制作多页面表单的组件。在这期间，上述例子对如何为你的站点生成多页面是个合理的指南。

Zend_Form 的国际化
Zend_Form
Zend Framework手册 中文版
Zend_Gdata
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Form
  • Zend_Form
  • Zend_Form 快速起步
  • 使用 Zend_Form_Element 生成表单元素
  • 使用 Zend_Form 生成表单
  • 使用 Zend_Form_Decorator 生成定制的表单标识（Markup）
  • Zend Framework 带有的标准表单元素
  • Zend Framework 带有的标准表单装饰器（Decorators）
  • Zend_Form 的国际化
  • Zend_Form 的高级用法


Zend_Gdata - Zend Framework Manual

Zend_Form 的高级用法
Zend Framework Reference
Zend Framework手册 中文版
Introduction

Zend_Gdata

Table of Contents
  • Introduction
  • Authenticating with AuthSub
  • Using the Book Search Data API
  • Authenticating with ClientLogin
  • Using Google Calendar
  • Using Google Documents List Data API
  • Using Google Health
  • Using Google Spreadsheets
  • Using Google Apps Provisioning
  • Using Google Base
  • Using Picasa Web Albums
  • Using the YouTube Data API
  • Catching Gdata Exceptions
Zend_Form 的高级用法
Zend Framework Reference
Zend Framework手册 中文版
Introduction
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


Introduction - Zend Framework Manual

Zend_Gdata
Zend_Gdata
Zend Framework手册 中文版
Authenticating with AuthSub

Introduction

Google Data APIs provide programmatic interface to some of Google's online services. The Google data Protocol is based upon the » Atom Publishing Protocol and allows client applications to retrieve data matching queries, post data, update data and delete data using standard HTTP and the Atom syndication formation. The Zend_Gdata component is a PHP 5 interface for accessing Google Data from PHP. The Zend_Gdata component also supports accessing other services implementing the Atom Publishing Protocol.

See » http://code.google.com/apis/gdata/ for more information about Google Data API.

The services that are accessible by Zend_Gdata include the following:

  • Google Calendar is a popular online calendar application.

  • Google Spreadsheets provides an online collaborative spreadsheets tool which can be used as a simple data store for your applications.

  • Google Documents List provides an online list of all spreadsheets, word processing documents, and presentations stored in a Google account.

  • Google Provisioning provides the ability to create, retrieve, update, and delete user accounts, nicknames, and email lists on a Google Apps hosted domain.

  • Google Base provides the ability to retrieve, post, update, and delete items in Google Base.

  • YouTube provides the ability to search and retrieve videos, comments, favorites, subscriptions, user profiles and more.

  • Picasa Web Albums provides an online photo sharing application.

  • » Google Blogger is a popular Internet provider of "push-button publishing" and syndication.

  • Google CodeSearch allows you to search public source code from many projects.

  • Google Notebook allows you to view public Notebook content.

Note: Unsupported services
 Zend_Gdata does not provide an interface to any other Google service, such as Search, Gmail, Translation, or Maps. Only services that support the Google Data API are supported.

Structure of Zend_Gdata

Zend_Gata is composed of several types of classes:

  • Service classes - inheriting from Zend_Gdata_App. These also include other classes such as Zend_Gdata, Zend_Gdata_Spreadsheets, etc. These classes enable interacting with APP or GData services and provide the ability to retrieve feeds, retrieve entries, post entries, update entries and delete entries.

  • Query classes - inheriting from Zend_Gdata_Query. These also include other classes for specific services, such as Zend_Gdata_Spreadsheets_ListQuery and Zend_Gdata_Spreadsheets_CellQuery. Query classes provide methods used to construct a query for data to be retrieved from GData services. Methods include getters and setters like setUpdatedMin(), setStartIndex(), and getPublishedMin(). The query classes also have a method to generate a URL representing the constructed query -- getQueryUrl. Alternatively, the query string component of the URL can be retrieved used the getQueryString() method.

  • Feed classes - inheriting from Zend_Gdata_App_Feed. These also include other classes such as Zend_Gdata_Feed, Zend_Gdata_Spreadsheets_SpreadsheetFeed, and Zend_Gdata_Spreadsheets_ListFeed. These classes represent feeds of entries retrieved from services. They are primarily used to retrieve data returned from services.

  • Entry classes - inheriting from Zend_Gdata_App_Entry. These also include other classes such as Zend_Gdata_Entry, and Zend_Gdata_Spreadsheets_ListEntry. These classes represent entries retrieved from services or used for constructing data to send to services. In addition to being able to set the properties of an entry (such as the spreadsheet cell value), you can use an entry object to send update or delete requests to a service. For example, you can call $entry->save() to save changes made to an entry back to service from which the entry initiated, or $entry->delete() to delete an entry from the server.

  • Other Data model classes - inheriting from Zend_Gdata_App_Extension. These include classes such as Zend_Gdata_App_Extension_Title (representing the atom:title XML element), Zend_Gdata_Extension_When (representing the gd:when XML element used by the GData Event "Kind"), and Zend_Gdata_Extension_Cell (representing the gs:cell XML element used by Google Spreadsheets). These classes are used purely to store the data retrieved back from services and for constructing data to be sent to services. These include getters and setters such as setText() to set the child text node of an element, getText() to retrieve the text node of an element, getStartTime() to retrieve the start time attribute of a When element, and other similiar methods. The data model classes also include methods such as getDOM() to retrieve a DOM representation of the element and all children and transferFromDOM() to construct a data model representation of a DOM tree.

Interacting with Google Services

Google data services are based upon the Atom Publishing Protocol (APP) and the Atom syndication format. To interact with APP or Google services using the Zend_Gdata component, you need to use the service classes such as Zend_Gdata_App, Zend_Gdata, Zend_Gdata_Spreadsheets, etc. These service classes provide methods to retrieve data from services as feeds, insert new entries into feeds, update entries, and delete entries.

Note: A full example of working with Zend_Gdata is available in the demos/Zend/Gdata directory. This example is runnable from the command-line, but the methods contained within are easily portable to a web application.

Obtaining instances of Zend_Gdata classes

The Zend Framework naming standards require that all classes be named based upon the directory structure in which they are located. For instance, extensions related to Spreadsheets are stored in: Zend/Gdata/Spreadsheets/Extension/... and, as a result of this, are named Zend_Gdata_Spreadsheets_Extension_.... This causes a lot of typing if you're trying to construct a new instance of a spreadsheet cell element!

We've implemented a magic factory method in all service classes (such as Zend_Gdata_App, Zend_Gdata, Zend_Gdata_Spreadsheets) that should make constructing new instances of data model, query and other classes much easier. This magic factory is implemented by using the magic __call method to intercept all attempts to call $service->newXXX(arg1, arg2, ...). Based off the value of XXX, a search is performed in all registered 'packages' for the desired class. Here's some examples:

  1. $ss = new Zend_Gdata_Spreadsheets();
  2.
  3. // creates a Zend_Gdata_App_Spreadsheets_CellEntry
  4. $entry = $ss->newCellEntry();
  5.
  6. // creates a Zend_Gdata_App_Spreadsheets_Extension_Cell
  7. $cell = $ss->newCell();
  8. $cell->setText('My cell value');
  9. $cell->setRow('1');
  10. $cell->setColumn('3');
  11. $entry->cell = $cell;
  12.
  13. // ... $entry can then be used to send an update to a Google Spreadsheet

Each service class in the inheritance tree is responsible for registering the appropriate 'packages' (directories) which are to be searched when calling the magic factory method.

Google Data Client Authentication

Most Google Data services require client applications to authenticate against the Google server before accessing private data, or saving or deleting data. There are two implementations of authentication for Google Data: AuthSub and ClientLogin. Zend_Gdata offers class interfaces for both of these methods.

Most other types of queries against Google Data services do not require authentication.

Dependencies

Zend_Gdata makes use of Zend_Http_Client to send requests to google.com and fetch results. The response to most Google Data requests is returned as a subclass of the Zend_Gdata_App_Feed or Zend_Gdata_App_Entry classes.

Zend_Gdata assumes your PHP application is running on a host that has a direct connection to the Internet. The Zend_Gdata client operates by contacting Google Data servers.

Creating a new Gdata client

Create a new object of class Zend_Gdata_App, Zend_Gdata, or one of the subclasses available that offer helper methods for service-specific behavior.

The single optional parameter to the Zend_Gdata_App constructor is an instance of Zend_Http_Client. If you don't pass this parameter, Zend_Gdata creates a default Zend_Http_Client object, which will not have associated credentials to access private feeds. Specifying the Zend_Http_Client object also allows you to pass configuration options to that client object.

  1. $client = new Zend_Http_Client();
  2. $client->setConfig( ...options... );
  3.
  4. $gdata = new Zend_Gdata($client);

Beginning with Zend Framework 1.7, support has been added for protocol versioning. This allows the client and server to support new features while maintaining backwards compatibility. While most services will manage this for you, if you create a Zend_Gdata instance directly (as opposed to one of its subclasses), you may need to specify the desired protocol version to access certain server functionality.

  1. $client = new Zend_Http_Client();
  2. $client->setConfig( ...options... );
  3.
  4. $gdata = new Zend_Gdata($client);
  5. $gdata->setMajorProtocolVersion(2);
  6. $gdata->setMinorProtocolVersion(null);

Also see the sections on authentication for methods to create an authenticated Zend_Http_Client object.

Common Query Parameters

You can specify parameters to customize queries with Zend_Gdata. Query parameters are specified using subclasses of Zend_Gdata_Query. The Zend_Gdata_Query class includes methods to set all query parameters used throughout GData services. Individual services, such as Spreadsheets, also provide query classes to defined parameters which are custom to the particular service and feeds. Spreadsheets includes a CellQuery class to query the Cell Feed and a ListQuery class to query the List Feed, as different query parameters are applicable to each of those feed types. The GData-wide parameters are described below.

  • The q parameter specifies a full-text query. The value of the parameter is a string.

    Set this parameter with the setQuery() function.

  • The alt parameter specifies the feed type. The value of the parameter can be atom, rss, json, or json-in-script. If you don't specify this parameter, the default feed type is atom. NOTE: Only the output of the atom feed format can be processed using Zend_Gdata. The Zend_Http_Client could be used to retrieve feeds in other formats, using query URLs generated by the Zend_Gdata_Query class and its subclasses.

    Set this parameter with the setAlt() function.

  • The maxResults parameter limits the number of entries in the feed. The value of the parameter is an integer. The number of entries returned in the feed will not exceed this value.

    Set this parameter with the setMaxResults() function.

  • The startIndex parameter specifies the ordinal number of the first entry returned in the feed. Entries before this number are skipped.

    Set this parameter with the setStartIndex() function.

  • The updatedMin and updatedMax parameters specify bounds on the entry date. If you specify a value for updatedMin, no entries that were updated earlier than the date you specify are included in the feed. Likewise no entries updated after the date specified by updatedMax are included.

    You can use numeric timestamps, or a variety of date/time string representations as the value for these parameters.

    Set this parameter with the setUpdatedMin() and setUpdatedMax() functions.

There is a get function for each set function.

  1. $query = new Zend_Gdata_Query();
  2. $query->setMaxResults(10);
  3. echo $query->getMaxResults();   // returns 10

The Zend_Gdata class also implements "magic" getter and setter methods, so you can use the name of the parameter as a virtual member of the class.

  1. $query = new Zend_Gdata_Query();
  2. $query->maxResults = 10;
  3. echo $query->maxResults;        // returns 10

You can clear all parameters with the resetParameters() function. This is useful to do if you reuse a Zend_Gdata object for multiple queries.

  1. $query = new Zend_Gdata_Query();
  2. $query->maxResults = 10;
  3. // ...get feed...
  4.
  5. $query->resetParameters();      // clears all parameters
  6. // ...get a different feed...

Fetching a Feed

Use the getFeed() function to retrieve a feed from a specified URI. This function returns an instance of class specified as the second argument to getFeed, which defaults to Zend_Gdata_Feed.

  1. $gdata = new Zend_Gdata();
  2. $query = new Zend_Gdata_Query(
  3.         'http://www.blogger.com/feeds/blogID/posts/default');
  4. $query->setMaxResults(10);
  5. $feed = $gdata->getFeed($query);

See later sections for special functions in each helper class for Google Data services. These functions help you to get feeds from the URI that is appropriate for the respective service.

Working with Multi-page Feeds

When retrieving a feed that contains a large number of entries, the feed may be broken up into many smaller "pages" of feeds. When this occurs, each page will contain a link to the next page in the series. This link can be accessed by calling getLink('next'). The following example shows how to retrieve the next page of a feed:

  1. function getNextPage($feed) {
  2.     $nextURL = $feed->getLink('next');
  3.     if ($nextURL !== null) {
  4.         return $gdata->getFeed($nextURL);
  5.     } else {
  6.         return null;
  7.     }
  8. }

If you would prefer not to work with pages in your application, pass the first page of the feed into Zend_Gdata_App::retrieveAllEntriesForFeed(), which will consolidate all entries from each page into a single feed. This example shows how to use this function:

  1. $gdata = new Zend_Gdata();
  2. $query = new Zend_Gdata_Query(
  3.         'http://www.blogger.com/feeds/blogID/posts/default');
  4. $feed = $gdata->retrieveAllEntriesForFeed($gdata->getFeed($query));

Keep in mind when calling this function that it may take a long time to complete on large feeds. You may need to increase PHP's execution time limit by calling set_time_limit().

Working with Data in Feeds and Entries

After retrieving a feed, you can read the data from the feed or the entries contained in the feed using either the accessors defined in each of the data model classes or the magic accessors. Here's an example:

  1. $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
  2. $gdata = new Zend_Gdata($client);
  3. $query = new Zend_Gdata_Query(
  4.         'http://www.blogger.com/feeds/blogID/posts/default');
  5. $query->setMaxResults(10);
  6. $feed = $gdata->getFeed($query);
  7. foreach ($feed as $entry) {
  8.     // using the magic accessor
  9.     echo 'Title: ' . $entry->title->text;
  10.     // using the defined accessors
  11.     echo 'Content: ' . $entry->getContent()->getText();
  12. }

Updating Entries

After retrieving an entry, you can update that entry and save changes back to the server. Here's an example:

  1. $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
  2. $gdata = new Zend_Gdata($client);
  3. $query = new Zend_Gdata_Query(
  4.         'http://www.blogger.com/feeds/blogID/posts/default');
  5. $query->setMaxResults(10);
  6. $feed = $gdata->getFeed($query);
  7. foreach ($feed as $entry) {
  8.     // update the title to append 'NEW'
  9.     echo 'Old Title: ' . $entry->title->text;
  10.     $entry->title->text = $entry->title->text . ' NEW';
  11.
  12.     // update the entry on the server
  13.     $newEntry = $entry->save();
  14.     echo 'New Title: ' . $newEntry->title->text;
  15. }

Posting Entries to Google Servers

The Zend_Gdata object has a function insertEntry() with which you can upload data to save new entries to Google Data services.

You can use the data model classes for each service to construct the appropriate entry to post to Google's services. The insertEntry() function will accept a child of Zend_Gdata_App_Entry as data to post to the service. The method returns a child of Zend_Gdata_App_Entry which represents the state of the entry as it was returned from the server.

Alternatively, you could construct the XML structure for an entry as a string and pass the string to the insertEntry() function.

  1. $gdata = new Zend_Gdata($authenticatedHttpClient);
  2.
  3. $entry = $gdata->newEntry();
  4. $entry->title = $gdata->newTitle('Playing football at the park');
  5. $content =
  6.     $gdata->newContent('We will visit the park and play football');
  7. $content->setType('text');
  8. $entry->content = $content;
  9.
  10. $entryResult = $gdata->insertEntry($entry,
  11.         'http://www.blogger.com/feeds/blogID/posts/default');
  12.
  13. echo 'The <id> of the resulting entry is: ' . $entryResult->id->text;

To post entries, you must be using an authenticated Zend_Http_Client that you created using the Zend_Gdata_AuthSub or Zend_Gdata_ClientLogin classes.

Deleting Entries on Google Servers

Option 1: The Zend_Gdata object has a function delete() with which you can delete entries from Google Data services. Pass the edit URL value from a feed entry to the delete() method.

Option 2: Alternatively, you can call $entry->delete() on an entry retrieved from a Google service.

  1. $gdata = new Zend_Gdata($authenticatedHttpClient);
  2. // a Google Data feed
  3. $feedUri = ...;
  4. $feed = $gdata->getFeed($feedUri);
  5. foreach ($feed as $feedEntry) {
  6.     // Option 1 - delete the entry directly
  7.     $feedEntry->delete();
  8.     // Option 2 - delete the entry by passing the edit URL to
  9.     // $gdata->delete()
  10.     // $gdata->delete($feedEntry->getEditLink()->href);
  11. }

To delete entries, you must be using an authenticated Zend_Http_Client that you created using the Zend_Gdata_AuthSub or Zend_Gdata_ClientLogin classes.

Zend_Gdata
Zend_Gdata
Zend Framework手册 中文版
Authenticating with AuthSub
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Gdata
  • Introduction
  • Authenticating with AuthSub
  • Using the Book Search Data API
  • Authenticating with ClientLogin
  • Using Google Calendar
  • Using Google Documents List Data API
  • Using Google Health
  • Using Google Spreadsheets
  • Using Google Apps Provisioning
  • Using Google Base
  • Using Picasa Web Albums
  • Using the YouTube Data API
  • Catching Gdata Exceptions


Authenticating with AuthSub - Zend Framework Manual

Introduction
Zend_Gdata
Zend Framework手册 中文版
Using the Book Search Data API

Authenticating with AuthSub

The AuthSub mechanism enables you to write web applications that acquire authenticated access Google Data services, without having to write code that handles user credentials.

See » http://code.google.com/apis/accounts/AuthForWebApps.html for more information about Google Data AuthSub authentication.

The Google documentation says the ClientLogin mechanism is appropriate for "installed applications" whereas the AuthSub mechanism is for "web applications." The difference is that AuthSub requires interaction from the user, and a browser interface that can react to redirection requests. The ClientLogin solution uses PHP code to supply the account credentials; the user is not required to enter her credentials interactively.

The account credentials supplied via the AuthSub mechanism are entered by the user of the web application. Therefore they must be account credentials that are known to that user.

Note: Registered applications
 Zend_Gdata currently does not support use of secure tokens, because the AuthSub authentication does not support passing a digital certificate to acquire a secure token.

Creating an AuthSub authenticated Http Client

Your PHP application should provide a hyperlink to the Google URL that performs authentication. The static function Zend_Gdata_AuthSub::getAuthSubTokenUri() provides the correct URL. The arguments to this function include the URL to your PHP application so that Google can redirect the user's browser back to your application after the user's credentials have been verified.

After Google's authentication server redirects the user's browser back to the current application, a GET request parameter is set, called token. The value of this parameter is a single-use token that can be used for authenticated access. This token can be converted into a multi-use token and stored in your session.

Then use the token value in a call to Zend_Gdata_AuthSub::getHttpClient(). This function returns an instance of Zend_Http_Client, with appropriate headers set so that subsequent requests your application submits using that Http Client are also authenticated.

Below is an example of PHP code for a web application to acquire authentication to use the Google Calendar service and create a Zend_Gdata client object using that authenticated Http Client.

  1. $my_calendar = 'http://www.google.com/calendar/feeds/default/private/full';
  2.
  3. if (!isset($_SESSION['cal_token'])) {
  4.     if (isset($_GET['token'])) {
  5.         // You can convert the single-use token to a session token.
  6.         $session_token =
  7.             Zend_Gdata_AuthSub::getAuthSubSessionToken($_GET['token']);
  8.         // Store the session token in our session.
  9.         $_SESSION['cal_token'] = $session_token;
  10.     } else {
  11.         // Display link to generate single-use token
  12.         $googleUri = Zend_Gdata_AuthSub::getAuthSubTokenUri(
  13.             'http://'. $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'],
  14.             $my_calendar, 0, 1);
  15.         echo "Click <a href='$googleUri'>here</a> " .
  16.              "to authorize this application.";
  17.         exit();
  18.     }
  19. }
  20.
  21. // Create an authenticated HTTP Client to talk to Google.
  22. $client = Zend_Gdata_AuthSub::getHttpClient($_SESSION['cal_token']);
  23.
  24. // Create a Gdata object using the authenticated Http Client
  25. $cal = new Zend_Gdata_Calendar($client);

Revoking AuthSub authentication

To terminate the authenticated status of a given token, use the Zend_Gdata_AuthSub::AuthSubRevokeToken() static function. Otherwise, the token is still valid for some time.

  1. // Carefully construct this value to avoid application security problems.
  2. $php_self = htmlentities(substr($_SERVER['PHP_SELF'],
  3.                          0,
  4.                          strcspn($_SERVER['PHP_SELF'], "\n\r")),
  5.                          ENT_QUOTES);
  6.
  7. if (isset($_GET['logout'])) {
  8.     Zend_Gdata_AuthSub::AuthSubRevokeToken($_SESSION['cal_token']);
  9.     unset($_SESSION['cal_token']);
  10.     header('Location: ' . $php_self);
  11.     exit();
  12. }

Note: Security notes
 The treatment of the $php_self variable in the example above is a general security guideline, it is not specific to Zend_Gdata. You should always filter content you output to http headers.
Regarding revoking authentication tokens, it is recommended to do this when the user is finished with her Google Data session. The possibility that someone can intercept the token and use it for malicious purposes is very small, but nevertheless it is a good practice to terminate authenticated access to any service.

Introduction
Zend_Gdata
Zend Framework手册 中文版
Using the Book Search Data API
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Gdata
  • Introduction
  • Authenticating with AuthSub
  • Using the Book Search Data API
  • Authenticating with ClientLogin
  • Using Google Calendar
  • Using Google Documents List Data API
  • Using Google Health
  • Using Google Spreadsheets
  • Using Google Apps Provisioning
  • Using Google Base
  • Using Picasa Web Albums
  • Using the YouTube Data API
  • Catching Gdata Exceptions


Using the Book Search Data API - Zend Framework Manual

Authenticating with AuthSub
Zend_Gdata
Zend Framework手册 中文版
Authenticating with ClientLogin

Using the Book Search Data API

The Google Book Search Data API allows client applications to view and update Book Search content in the form of Google Data API feeds.

Your client application can use the Book Search Data API to issue full-text searches for books and to retrieve standard book information, ratings, and reviews. You can also access individual users' » library collections and public reviews. Finally, your application can submit authenticated requests to enable users to create and modify library collections, ratings, labels, reviews, and other account-specific entities.

For more information on the Book Search Data API, please refer to the official » PHP Developer's Guide on code.google.com.

Authenticating to the Book Search service

You can access both public and private feeds using the Book Search Data API. Public feeds don't require any authentication, but they are read-only. If you want to modify user libraries, submit reviews or ratings, or add labels, then your client needs to authenticate before requesting private feeds. It can authenticate using either of two approaches: AuthSub proxy authentication or ClientLogin username/password authentication. Please refer to the » Authentication section in the PHP Developer's Guide for more detail.

Searching for books

The Book Search Data API provides a number of feeds that list collections of books.

The most common action is to retrieve a list of books that match a search query. To do so you create a VolumeQuery object and pass it to the Books::getVolumeFeed method.

For example, to perform a keyword query, with a filter on viewability to restrict the results to partial or full view books, use the setMinViewability and setQuery methods of the VolumeQuery object. The following code snippet prints the title and viewability of all volumes whose metadata or text matches the query term "domino":

  1. $books = new Zend_Gdata_Books();
  2. $query = $books->newVolumeQuery();
  3.
  4. $query->setQuery('domino');
  5. $query->setMinViewability('partial_view');
  6.
  7. $feed = $books->getVolumeFeed($query);
  8.
  9. foreach ($feed as $entry) {
  10.     echo $entry->getVolumeId();
  11.     echo $entry->getTitle();
  12.     echo $entry->getViewability();
  13. }

The Query class, and subclasses like VolumeQuery, are responsible for constructing feed URLs. The VolumeQuery shown above constructs a URL equivalent to the following:

  1. http://www.google.com/books/feeds/volumes?q=keyword&amp;min-viewability=partial

Note: Since Book Search results are public, you can issue a Book Search query without authentication.

Here are some of the most common VolumeQuery methods for setting search parameters:

setQuery: Specifies a search query term. Book Search searches all book metadata and full text for books matching the term. Book metadata includes titles, keywords, descriptions, author names, and subjects. Note that any spaces, quotes or other punctuation in the parameter value must be URL-escaped. (Use a plus (+) for a space.) To search for an exact phrase, enclose the phrase in quotation marks. For example, to search for books matching the phrase "spy plane", set the q parameter to %22spy+plane%22. You can also use any of the » advanced search operators supported by Book Search. For example, jane+austen+-inauthor:austen returns matches that mention (but are not authored by) Jane Austen.

setStartIndex: Specifies the index of the first matching result that should be included in the result set. This parameter uses a one-based index, meaning the first result is 1, the second result is 2 and so forth. This parameter works in conjunction with the max-results parameter to determine which results to return. For example, to request the third set of 10 results—results 21-30—set the start-index parameter to 21 and the max-results parameter to 10. Note: This isn't a general cursoring mechanism. If you first send a query with ?start-index=1&max-results=10 and then send another query with ?start-index=11&max-results=10, the service cannot guarantee that the results are equivalent to ?start-index=1&max-results=20, because insertions and deletions could have taken place in between the two queries.

setMaxResults: Specifies the maximum number of results that should be included in the result set. This parameter works in conjunction with the start-index parameter to determine which results to return. The default value of this parameter is 10 and the maximum value is 20.

setMinViewability: Allows you to filter the results according to the books' » viewability status. This parameter accepts one of three values: 'none' (the default, returning all matching books regardless of viewability), 'partial_view' (returning only books that the user can preview or view in their entirety), or 'full_view' (returning only books that the user can view in their entirety).

Partner Co-Branded Search

Google Book Search provides » Co-Branded Search, which lets content partners provide full-text search of their books from their own websites.

If you are a partner who wants to do Co-Branded Search using the Book Search Data API, you may do so by modifying the feed URL above to point to your Co-Branded Search implementation. If, for example, a Co-Branded Search is available at the following URL:

  1. http://www.google.com/books/p/PARTNER_COBRAND_ID?q=ball

then you can obtain the same results using the Book Search Data API at the following URL:

  1. http://www.google.com/books/feeds/p/PARTNER_COBRAND_ID/volumes?q=ball+-soccer

To specify an alternate URL when querying a volume feed, you can provide an extra parameter to newVolumeQuery

  1. $query =
  2.     $books->newVolumeQuery('http://www.google.com/books/p/PARTNER_COBRAND_ID');

For additional information or support, visit our » Partner help center.

Using community features

Adding a rating

A user can add a rating to a book. Book Search uses a 1-5 rating system in which 1 is the lowest rating. Users cannot update or delete ratings.

To add a rating, add a Rating object to a VolumeEntry and post it to the annotation feed. In the example below, we start from an empty VolumeEntry object.

  1. $entry = new Zend_Gdata_Books_VolumeEntry();
  2. $entry->setId(new Zend_Gdata_App_Extension_Id(VOLUME_ID));
  3. $entry->setRating(new Zend_Gdata_Extension_Rating(3, 1, 5, 1));
  4. $books->insertVolume($entry, Zend_Gdata_Books::MY_ANNOTATION_FEED_URI);

Reviews

In addition to ratings, authenticated users can submit reviews or edit their reviews. For information on how to request previously submitted reviews, see » Retrieving annotations.

Adding a review

To add a review, add a Review object to a VolumeEntry and post it to the annotation feed. In the example below, we start from an existing VolumeEntry object.

  1. $annotationUrl = $entry->getAnnotationLink()->href;
  2. $review        = new Zend_Gdata_Books_Extension_Review();
  3.
  4. $review->setText("This book is amazing!");
  5. $entry->setReview($review);
  6. $books->insertVolume($entry, $annotationUrl);

Editing a review

To update an existing review, first you retrieve the review you want to update, then you modify it, and then you submit it to the annotation feed.

  1. $entryUrl = $entry->getId()->getText();
  2. $review   = new Zend_Gdata_Books_Extension_Review();
  3.
  4. $review->setText("This book is actually not that good!");
  5. $entry->setReview($review);
  6. $books->updateVolume($entry, $entryUrl);

Labels

You can use the Book Search Data API to label volumes with keywords. A user can submit, retrieve and modify labels. See » Retrieving annotations for how to read previously submitted labels.

Submitting a set of labels

To submit labels, add a Category object with the scheme LABELS_SCHEME to a VolumeEntry and post it to the annotation feed.

  1. $annotationUrl = $entry->getAnnotationLink()->href;
  2. $category      = new Zend_Gdata_App_Extension_Category(
  3.     'rated',
  4.     'http://schemas.google.com/books/2008/labels');
  5. $entry->setCategory(array($category));
  6. $books->insertVolume($entry, Zend_Gdata_Books::MY_ANNOTATION_FEED_URI);

Retrieving annotations: reviews, ratings, and labels

You can use the Book Search Data API to retrieve annotations submitted by a given user. Annotations include reviews, ratings, and labels. To retrieve any user's annotations, you can send an unauthenticated request that includes the user's user ID. To retrieve the authenticated user's annotations, use the value me as the user ID.

  1. $feed = $books->getVolumeFeed(
  2.             'http://www.google.com/books/feeds/users/USER_ID/volumes');
  3. <i>(or)</i>
  4. $feed = $books->getUserAnnotationFeed();
  5.
  6. // print title(s) and rating value
  7. foreach ($feed as $entry) {
  8.     foreach ($feed->getTitles() as $title) {
  9.         echo $title;
  10.     }
  11.     if ($entry->getRating()) {
  12.         echo 'Rating: ' . $entry->getRating()->getAverage();
  13.     }
  14. }

For a list of the supported query parameters, see the » query parameters section.

Deleting Annotations

If you retrieved an annotation entry containing ratings, reviews, and/or labels, you can remove all annotations by calling deleteVolume on that entry.

  1. $books->deleteVolume($entry);

Book collections and My Library

Google Book Search provides a number of user-specific book collections, each of which has its own feed.

The most important collection is the user's My Library, which represents the books the user would like to remember, organize, and share with others. This is the collection the user sees when accessing his or her » My Library page.

Retrieving books in a user's library

The following sections describe how to retrieve a list of books from a user's library, with or without query parameters.

You can query a Book Search public feed without authentication.

Retrieving all books in a user's library

To retrieve the user's books, send a query to the My Library feed. To get the library of the authenticated user, use me in place of USER_ID.

  1. $feed = $books->getUserLibraryFeed();

Note: The feed may not contain all of the user's books, because there's a default limit on the number of results returned. For more information, see the max-results query parameter in » Searching for books.

Searching for books in a user's library

Just as you can » search across all books, you can do a full-text search over just the books in a user's library. To do this, just set the appropriate paramters on the VolumeQuery object.

For example, the following query returns all the books in your library that contain the word "bear":

  1. $query = $books->newVolumeQuery(
  2.     'http://www.google.com/books/feeds/users' .
  3.     '/USER_ID/collections/library/volumes');
  4. $query->setQuery('bear');
  5. $feed = $books->getVolumeFeed($query);

For a list of the supported query parameters, see the » query parameters section. In addition, you can search for books that have been » labeled by the user:

  1. $query = $books->newVolumeQuery(
  2.     'http://www.google.com/books/feeds/users/' .
  3.     'USER_ID/collections/library/volumes');
  4. $query->setCategory(
  5. $query->setCategory('favorites');
  6. $feed = $books->getVolumeFeed($query);

Updating books in a user's library

You can use the Book Search Data API to add a book to, or remove a book from, a user's library. Ratings, reviews, and labels are valid across all the collections of a user, and are thus edited using the annotation feed (see » Using community features).

Adding a book to a library

After authenticating, you can add books to the current user's library.

You can either create an entry from scratch if you know the volume ID, or insert an entry read from any feed.

The following example creates a new entry and adds it to the library:

  1. $entry = new Zend_Gdata_Books_VolumeEntry();
  2. $entry->setId(new Zend_Gdata_App_Extension_Id(VOLUME_ID));
  3. $books->insertVolume(
  4.     $entry,
  5.     Zend_Gdata_Books::MY_LIBRARY_FEED_URI
  6. );

The following example adds an existing VolumeEntry object to the library:

  1. $books->insertVolume(
  2.     $entry,
  3.     Zend_Gdata_Books::MY_LIBRARY_FEED_URI
  4. );

Removing a book from a library

To remove a book from a user's library, call deleteVolume on the VolumeEntry object.

  1. $books->deleteVolume($entry);
Authenticating with AuthSub
Zend_Gdata
Zend Framework手册 中文版
Authenticating with ClientLogin
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Gdata
  • Introduction
  • Authenticating with AuthSub
  • Using the Book Search Data API
  • Authenticating with ClientLogin
  • Using Google Calendar
  • Using Google Documents List Data API
  • Using Google Health
  • Using Google Spreadsheets
  • Using Google Apps Provisioning
  • Using Google Base
  • Using Picasa Web Albums
  • Using the YouTube Data API
  • Catching Gdata Exceptions


Authenticating with ClientLogin - Zend Framework Manual

Using the Book Search Data API
Zend_Gdata
Zend Framework手册 中文版
Using Google Calendar

Authenticating with ClientLogin

The ClientLogin mechanism enables you to write PHP application that acquire authenticated access to Google Services, specifying a user's credentials in the Http Client.

See » http://code.google.com/apis/accounts/AuthForInstalledApps.html for more information about Google Data ClientLogin authentication.

The Google documentation says the ClientLogin mechanism is appropriate for "installed applications" whereas the AuthSub mechanism is for "web applications." The difference is that AuthSub requires interaction from the user, and a browser interface that can react to redirection requests. The ClientLogin solution uses PHP code to supply the account credentials; the user is not required to enter her credentials interactively.

The account credentials supplied via the ClientLogin mechanism must be valid credentials for Google services, but they are not required to be those of the user who is using the PHP application.

Creating a ClientLogin authenticated Http Client

The process of creating an authenticated Http client using the ClientLogin mechanism is to call the static function Zend_Gdata_ClientLogin::getHttpClient() and pass the Google account credentials in plain text. The return value of this function is an object of class Zend_Http_Client.

The optional third parameter is the name of the Google Data service. For instance, this can be 'cl' for Google Calendar. The default is "xapi", which is recognized by Google Data servers as a generic service name.

The optional fourth parameter is an instance of Zend_Http_Client. This allows you to set options in the client, such as proxy server settings. If you pass NULL for this parameter, a generic Zend_Http_Client object is created.

The optional fifth parameter is a short string that Google Data servers use to identify the client application for logging purposes. By default this is string "Zend-ZendFramework";

The optional sixth parameter is a string ID for a CAPTCHA challenge that has been issued by the server. It is only necessary when logging in after receiving a CAPTCHA challenge from a previous login attempt.

The optional seventh parameter is a user's response to a CAPTCHA challenge that has been issued by the server. It is only necessary when logging in after receiving a CAPTCHA challenge from a previous login attempt.

Below is an example of PHP code for a web application to acquire authentication to use the Google Calendar service and create a Zend_Gdata client object using that authenticated Zend_Http_Client.

  1. // Enter your Google account credentials
  2. $email = 'johndoe@gmail.com';
  3. $passwd = 'xxxxxxxx';
  4. try {
  5.    $client = Zend_Gdata_ClientLogin::getHttpClient($email, $passwd, 'cl');
  6. } catch (Zend_Gdata_App_CaptchaRequiredException $cre) {
  7.     echo 'URL of CAPTCHA image: ' . $cre->getCaptchaUrl() . "\n";
  8.     echo 'Token ID: ' . $cre->getCaptchaToken() . "\n";
  9. } catch (Zend_Gdata_App_AuthException $ae) {
  10.    echo 'Problem authenticating: ' . $ae->exception() . "\n";
  11. }
  12.
  13. $cal = new Zend_Gdata_Calendar($client);

Terminating a ClientLogin authenticated Http Client

There is no method to revoke ClientLogin authentication as there is in the AuthSub token-based solution. The credentials used in the ClientLogin authentication are the login and password to a Google account, and therefore these can be used repeatedly in the future.

Using the Book Search Data API
Zend_Gdata
Zend Framework手册 中文版
Using Google Calendar
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Gdata
  • Introduction
  • Authenticating with AuthSub
  • Using the Book Search Data API
  • Authenticating with ClientLogin
  • Using Google Calendar
  • Using Google Documents List Data API
  • Using Google Health
  • Using Google Spreadsheets
  • Using Google Apps Provisioning
  • Using Google Base
  • Using Picasa Web Albums
  • Using the YouTube Data API
  • Catching Gdata Exceptions


Using Google Calendar - Zend Framework Manual

Authenticating with ClientLogin
Zend_Gdata
Zend Framework手册 中文版
Using Google Documents List Data API

Using Google Calendar

You can use the Zend_Gdata_Calendar class to view, create, update, and delete events in the online Google Calendar service.

See » http://code.google.com/apis/calendar/overview.html for more information about the Google Calendar API.

Connecting To The Calendar Service

The Google Calendar API, like all GData APIs, is based off of the Atom Publishing Protocol (APP), an XML based format for managing web-based resources. Traffic between a client and the Google Calendar servers occurs over HTTP and allows for both authenticated and unauthenticated connections.

Before any transactions can occur, this connection needs to be made. Creating a connection to the calendar servers involves two steps: creating an HTTP client and binding a Zend_Gdata_Calendar service instance to that client.

Authentication

The Google Calendar API allows access to both public and private calendar feeds. Public feeds do not require authentication, but are read-only and offer reduced functionality. Private feeds offers the most complete functionality but requires an authenticated connection to the calendar servers. There are three authentication schemes that are supported by Google Calendar:

  • ClientAuth provides direct username/password authentication to the calendar servers. Since this scheme requires that users provide your application with their password, this authentication is only recommended when other authentication schemes are insufficient.

  • AuthSub allows authentication to the calendar servers via a Google proxy server. This provides the same level of convenience as ClientAuth but without the security risk, making this an ideal choice for web-based applications.

  • MagicCookie allows authentication based on a semi-random URL available from within the Google Calendar interface. This is the simplest authentication scheme to implement, but requires that users manually retrieve their secure URL before they can authenticate, doesn't provide access to calendar lists, and is limited to read-only access.

The Zend_Gdata library provides support for all three authentication schemes. The rest of this chapter will assume that you are familiar the authentication schemes available and how to create an appropriate authenticated connection. For more information, please see section the Authentication section of this manual or the » Authentication Overview in the Google Data API Developer's Guide.

Creating A Service Instance

In order to interact with Google Calendar, this library provides the Zend_Gdata_Calendar service class. This class provides a common interface to the Google Data and Atom Publishing Protocol models and assists in marshaling requests to and from the calendar servers.

Once deciding on an authentication scheme, the next step is to create an instance of Zend_Gdata_Calendar. The class constructor takes an instance of Zend_Http_Client as a single argument. This provides an interface for AuthSub and ClientAuth authentication, as both of these require creation of a special authenticated HTTP client. If no arguments are provided, an unauthenticated instance of Zend_Http_Client will be automatically created.

The example below shows how to create a Calendar service class using ClientAuth authentication:

  1. // Parameters for ClientAuth authentication
  2. $service = Zend_Gdata_Calendar::AUTH_SERVICE_NAME;
  3. $user = "sample.user@gmail.com";
  4. $pass = "pa$$w0rd";
  5.
  6. // Create an authenticated HTTP client
  7. $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
  8.
  9. // Create an instance of the Calendar service
  10. $service = new Zend_Gdata_Calendar($client);

A Calendar service using AuthSub can be created in a similar, though slightly more lengthy fashion:

  1. /*
  2. * Retrieve the current URL so that the AuthSub server knows where to
  3. * redirect the user after authentication is complete.
  4. */
  5. function getCurrentUrl()
  6. {
  7.     global $_SERVER;
  8.
  9.     // Filter php_self to avoid a security vulnerability.
  10.     $php_request_uri =
  11.         htmlentities(substr($_SERVER['REQUEST_URI'],
  12.                             0,
  13.                             strcspn($_SERVER['REQUEST_URI'], "\n\r")),
  14.                             ENT_QUOTES);
  15.
  16.     if (isset($_SERVER['HTTPS']) &&
  17.         strtolower($_SERVER['HTTPS']) == 'on') {
  18.         $protocol = 'https://';
  19.     } else {
  20.         $protocol = 'http://';
  21.     }
  22.     $host = $_SERVER['HTTP_HOST'];
  23.     if ($_SERVER['HTTP_PORT'] != '' &&
  24.         (($protocol == 'http://' && $_SERVER['HTTP_PORT'] != '80') ||
  25.         ($protocol == 'https://' && $_SERVER['HTTP_PORT'] != '443'))) {
  26.         $port = ':' . $_SERVER['HTTP_PORT'];
  27.     } else {
  28.         $port = '';
  29.     }
  30.     return $protocol . $host . $port . $php_request_uri;
  31. }
  32.
  33. /**
  34. * Obtain an AuthSub authenticated HTTP client, redirecting the user
  35. * to the AuthSub server to login if necessary.
  36. */
  37. function getAuthSubHttpClient()
  38. {
  39.     global $_SESSION, $_GET;
  40.
  41.     // if there is no AuthSub session or one-time token waiting for us,
  42.     // redirect the user to the AuthSub server to get one.
  43.     if (!isset($_SESSION['sessionToken']) && !isset($_GET['token'])) {
  44.         // Parameters to give to AuthSub server
  45.         $next = getCurrentUrl();
  46.         $scope = "http://www.google.com/calendar/feeds/";
  47.         $secure = false;
  48.         $session = true;
  49.
  50.         // Redirect the user to the AuthSub server to sign in
  51.
  52.         $authSubUrl = Zend_Gdata_AuthSub::getAuthSubTokenUri($next,
  53.                                                              $scope,
  54.                                                              $secure,
  55.                                                              $session);
  56.          header("HTTP/1.0 307 Temporary redirect");
  57.
  58.          header("Location: " . $authSubUrl);
  59.
  60.          exit();
  61.     }
  62.
  63.     // Convert an AuthSub one-time token into a session token if needed
  64.     if (!isset($_SESSION['sessionToken']) && isset($_GET['token'])) {
  65.         $_SESSION['sessionToken'] =
  66.             Zend_Gdata_AuthSub::getAuthSubSessionToken($_GET['token']);
  67.     }
  68.
  69.     // At this point we are authenticated via AuthSub and can obtain an
  70.     // authenticated HTTP client instance
  71.
  72.     // Create an authenticated HTTP client
  73.     $client = Zend_Gdata_AuthSub::getHttpClient($_SESSION['sessionToken']);
  74.     return $client;
  75. }
  76.
  77. // -> Script execution begins here <-
  78.
  79. // Make sure that the user has a valid session, so we can record the
  80. // AuthSub session token once it is available.
  81. session_start();
  82.
  83. // Create an instance of the Calendar service, redirecting the user
  84. // to the AuthSub server if necessary.
  85. $service = new Zend_Gdata_Calendar(getAuthSubHttpClient());

Finally, an unauthenticated server can be created for use with either public feeds or MagicCookie authentication:

  1. // Create an instance of the Calendar service using an unauthenticated
  2. // HTTP client
  3.
  4. $service = new Zend_Gdata_Calendar();

Note that MagicCookie authentication is not supplied with the HTTP connection, but is instead specified along with the desired visibility when submitting queries. See the section on retrieving events below for an example.

Retrieving A Calendar List

The calendar service supports retrieving a list of calendars for the authenticated user. This is the same list of calendars which are displayed in the Google Calendar UI, except those marked as "hidden" are also available.

The calendar list is always private and must be accessed over an authenticated connection. It is not possible to retrieve another user's calendar list and it cannot be accessed using MagicCookie authentication. Attempting to access a calendar list without holding appropriate credentials will fail and result in a 401 (Authentication Required) status code.

  1. $service = Zend_Gdata_Calendar::AUTH_SERVICE_NAME;
  2. $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
  3. $service = new Zend_Gdata_Calendar($client);
  4.
  5. try {
  6.     $listFeed= $service->getCalendarListFeed();
  7. } catch (Zend_Gdata_App_Exception $e) {
  8.     echo "Error: " . $e->getMessage();
  9. }

Calling getCalendarListFeed() creates a new instance of Zend_Gdata_Calendar_ListFeed containing each available calendar as an instance of Zend_Gdata_Calendar_ListEntry. After retrieving the feed, you can use the iterator and accessors contained within the feed to inspect the enclosed calendars.

  1. echo "<h1>Calendar List Feed</h1>";
  2. echo "<ul>";
  3. foreach ($listFeed as $calendar) {
  4.     echo "<li>" . $calendar->title .
  5.          " (Event Feed: " . $calendar->id . ")</li>";
  6. }
  7. echo "</ul>";

Retrieving Events

Like the list of calendars, events are also retrieved using the Zend_Gdata_Calendar service class. The event list returned is of type Zend_Gdata_Calendar_EventFeed and contains each event as an instance of Zend_Gdata_Calendar_EventEntry. As before, the iterator and accessors contained within the event feed instance allow inspection of individual events.

Queries

When retrieving events using the Calendar API, specially constructed query URLs are used to describe what events should be returned. The Zend_Gdata_Calendar_EventQuery class simplifies this task by automatically constructing a query URL based on provided parameters. A full list of these parameters is available at the » Queries section of the Google Data APIs Protocol Reference. However, there are three parameters that are worth special attention:

  • User is used to specify the user whose calendar is being searched for, and is specified as an email address. If no user is provided, "default" will be used instead to indicate the currently authenticated user (if authenticated).

  • Visibility specifies whether a users public or private calendar should be searched. If using an unauthenticated session and no MagicCookie is available, only the public feed will be available.

  • Projection specifies how much data should be returned by the server and in what format. In most cases you will want to use the "full" projection. Also available is the "basic" projection, which places most meta-data into each event's content field as human readable text, and the "composite" projection which includes complete text for any comments alongside each event. The "composite" view is often much larger than the "full" view.

Retrieving Events In Order Of Start Time

The example below illustrates the use of the Zend_Gdata_Query class and specifies the private visibility feed, which requires that an authenticated connection is available to the calendar servers. If a MagicCookie is being used for authentication, the visibility should be instead set to "private-magicCookieValue", where magicCookieValue is the random string obtained when viewing the private XML address in the Google Calendar UI. Events are requested chronologically by start time and only events occurring in the future are returned.

  1. $query = $service->newEventQuery();
  2. $query->setUser('default');
  3. // Set to $query->setVisibility('private-magicCookieValue') if using
  4. // MagicCookie auth
  5. $query->setVisibility('private');
  6. $query->setProjection('full');
  7. $query->setOrderby('starttime');
  8. $query->setFutureevents('true');
  9.
  10. // Retrieve the event list from the calendar server
  11. try {
  12.     $eventFeed = $service->getCalendarEventFeed($query);
  13. } catch (Zend_Gdata_App_Exception $e) {
  14.     echo "Error: " . $e->getMessage();
  15. }
  16.
  17. // Iterate through the list of events, outputting them as an HTML list
  18. echo "<ul>";
  19. foreach ($eventFeed as $event) {
  20.     echo "<li>" . $event->title . " (Event ID: " . $event->id . ")</li>";
  21. }
  22. echo "</ul>";

Additional properties such as ID, author, when, event status, visibility, web content, and content, among others are available within Zend_Gdata_Calendar_EventEntry. Refer to the » Zend Framework API Documentation and the » Calendar Protocol Reference for a complete list.

Retrieving Events In A Specified Date Range

To print out all events within a certain range, for example from December 1, 2006 through December 15, 2007, add the following two lines to the previous sample. Take care to remove "$query->setFutureevents('true')", since futureevents will override startMin and startMax.

  1. $query->setStartMin('2006-12-01');
  2. $query->setStartMax('2006-12-16');

Note that startMin is inclusive whereas startMax is exclusive. As a result, only events through 2006-12-15 23:59:59 will be returned.

Retrieving Events By Fulltext Query

To print out all events which contain a specific word, for example "dogfood", use the setQuery() method when creating the query.

  1. $query->setQuery("dogfood");

Retrieving Individual Events

Individual events can be retrieved by specifying their event ID as part of the query. Instead of calling getCalendarEventFeed(), getCalendarEventEntry() should be called instead.

  1. $query = $service->newEventQuery();
  2. $query->setUser('default');
  3. $query->setVisibility('private');
  4. $query->setProjection('full');
  5. $query->setEvent($eventId);
  6.
  7. try {
  8.     $event = $service->getCalendarEventEntry($query);
  9. } catch (Zend_Gdata_App_Exception $e) {
  10.     echo "Error: " . $e->getMessage();
  11. }

In a similar fashion, if the event URL is known, it can be passed directly into getCalendarEntry() to retrieve a specific event. In this case, no query object is required since the event URL contains all the necessary information to retrieve the event.

  1. $eventURL = "http://www.google.com/calendar/feeds/default/private"
  2.           . "/full/g829on5sq4ag12se91d10uumko";
  3.
  4. try {
  5.     $event = $service->getCalendarEventEntry($eventURL);
  6. } catch (Zend_Gdata_App_Exception $e) {
  7.     echo "Error: " . $e->getMessage();
  8. }

Creating Events

Creating Single-Occurrence Events

Events are added to a calendar by creating an instance of Zend_Gdata_EventEntry and populating it with the appropriate data. The calendar service instance (Zend_Gdata_Calendar) is then used to used to transparently covert the event into XML and POST it to the calendar server. Creating events requires either an AuthSub or ClientAuth authenticated connection to the calendar server.

At a minimum, the following attributes should be set:

  • Title provides the headline that will appear above the event within the Google Calendar UI.

  • When indicates the duration of the event and, optionally, any reminders that are associated with it. See the next section for more information on this attribute.

Other useful attributes that may optionally set include:

  • Author provides information about the user who created the event.

  • Content provides additional information about the event which appears when the event details are requested from within Google Calendar.

  • EventStatus indicates whether the event is confirmed, tentative, or canceled.

  • Hidden removes the event from the Google Calendar UI.

  • Transparency indicates whether the event should be consume time on the user's free/busy list.

  • WebContent allows links to external content to be provided within an event.

  • Where indicates the location of the event.

  • Visibility allows the event to be hidden from the public event lists.

For a complete list of event attributes, refer to the » Zend Framework API Documentation and the » Calendar Protocol Reference. Attributes that can contain multiple values, such as where, are implemented as arrays and need to be created accordingly. Be aware that all of these attributes require objects as parameters. Trying instead to populate them using strings or primitives will result in errors during conversion to XML.

Once the event has been populated, it can be uploaded to the calendar server by passing it as an argument to the calendar service's insertEvent() function.

  1. // Create a new entry using the calendar service's magic factory method
  2. $event= $service->newEventEntry();
  3.
  4. // Populate the event with the desired information
  5. // Note that each attribute is crated as an instance of a matching class
  6. $event->title = $service->newTitle("My Event");
  7. $event->where = array($service->newWhere("Mountain View, California"));
  8. $event->content =
  9.     $service->newContent(" This is my awesome event. RSVP required.");
  10.
  11. // Set the date using RFC 3339 format.
  12. $startDate = "2008-01-20";
  13. $startTime = "14:00";
  14. $endDate = "2008-01-20";
  15. $endTime = "16:00";
  16. $tzOffset = "-08";
  17.
  18. $when = $service->newWhen();
  19. $when->startTime = "{$startDate}T{$startTime}:00.000{$tzOffset}:00";
  20. $when->endTime = "{$endDate}T{$endTime}:00.000{$tzOffset}:00";
  21. $event->when = array($when);
  22.
  23. // Upload the event to the calendar server
  24. // A copy of the event as it is recorded on the server is returned
  25. $newEvent = $service->insertEvent($event);

Event Schedules and Reminders

An event's starting time and duration are determined by the value of its when property, which contains the properties startTime, endTime, and valueString. StartTime and EndTime control the duration of the event, while the valueString property is currently unused.

All-day events can be scheduled by specifying only the date omitting the time when setting startTime and endTime. Likewise, zero-duration events can be specified by omitting the endTime. In all cases, date/time values should be provided in » RFC3339 format.

  1. // Schedule the event to occur on December 05, 2007 at 2 PM PST (UTC-8)
  2. // with a duration of one hour.
  3. $when = $service->newWhen();
  4. $when->startTime = "2007-12-05T14:00:00-08:00";
  5. $when->endTime="2007-12-05T15:00:00:00-08:00";
  6.
  7. // Apply the when property to an event
  8. $event->when = array($when);

The when attribute also controls when reminders are sent to a user. Reminders are stored in an array and each event may have up to find reminders associated with it.

For a reminder to be valid, it needs to have two attributes set: method and a time. Method can accept one of the following strings: "alert", "email", or "sms". The time should be entered as an integer and can be set with either the property minutes, hours, days, or absoluteTime. However, a valid request may only have one of these attributes set. If a mixed time is desired, convert to the most precise unit available. For example, 1 hour and 30 minutes should be entered as 90 minutes.

  1. // Create a new reminder object. It should be set to send an email
  2. // to the user 10 minutes beforehand.
  3. $reminder = $service->newReminder();
  4. $reminder->method = "email";
  5. $reminder->minutes = "10";
  6.
  7. // Apply the reminder to an existing event's when property
  8. $when = $event->when[0];
  9. $when->reminders = array($reminder);

Creating Recurring Events

Recurring events are created the same way as single-occurrence events, except a recurrence attribute should be provided instead of a where attribute. The recurrence attribute should hold a string describing the event's recurrence pattern using properties defined in the iCalendar standard (» RFC 2445).

Exceptions to the recurrence pattern will usually be specified by a distinct recurrenceException attribute. However, the iCalendar standard provides a secondary format for defining recurrences, and the possibility that either may be used must be accounted for.

Due to the complexity of parsing recurrence patterns, further information on this them is outside the scope of this document. However, more information can be found in the » Common Elements section of the Google Data APIs Developer Guide, as well as in RFC 2445.

  1. // Create a new entry using the calendar service's magic factory method
  2. $event= $service->newEventEntry();
  3.
  4. // Populate the event with the desired information
  5. // Note that each attribute is crated as an instance of a matching class
  6. $event->title = $service->newTitle("My Recurring Event");
  7. $event->where = array($service->newWhere("Palo Alto, California"));
  8. $event->content =
  9.     $service->newContent(' This is my other awesome event, ' .
  10.                          ' occurring all-day every Tuesday from .
  11.                          '2007-05-01 until 207-09-04. No RSVP required.');
  12.
  13. // Set the duration and frequency by specifying a recurrence pattern.
  14.
  15. $recurrence = "DTSTART;VALUE=DATE:20070501\r\n" .
  16.         "DTEND;VALUE=DATE:20070502\r\n" .
  17.         "RRULE:FREQ=WEEKLY;BYDAY=Tu;UNTIL=20070904\r\n";
  18.
  19. $event->recurrence = $service->newRecurrence($recurrence);
  20.
  21. // Upload the event to the calendar server
  22. // A copy of the event as it is recorded on the server is returned
  23. $newEvent = $service->insertEvent($event);

Using QuickAdd

QuickAdd is a feature which allows events to be created using free-form text entry. For example, the string "Dinner at Joe's Diner on Thursday" would create an event with the title "Dinner", location "Joe's Diner", and date "Thursday". To take advantage of QuickAdd, create a new QuickAdd property set to TRUE and store the freeform text as a content property.

  1. // Create a new entry using the calendar service's magic factory method
  2. $event= $service->newEventEntry();
  3.
  4. // Populate the event with the desired information
  5. $event->content= $service->newContent("Dinner at Joe's Diner on Thursday");
  6. $event->quickAdd = $service->newQuickAdd("true");
  7.
  8. // Upload the event to the calendar server
  9. // A copy of the event as it is recorded on the server is returned
  10. $newEvent = $service->insertEvent($event);

Modifying Events

Once an instance of an event has been obtained, the event's attributes can be locally modified in the same way as when creating an event. Once all modifications are complete, calling the event's save() method will upload the changes to the calendar server and return a copy of the event as it was created on the server.

In the event another user has modified the event since the local copy was retrieved, save() will fail and the server will return a 409 (Conflict) status code. To resolve this a fresh copy of the event must be retrieved from the server before attempting to resubmit any modifications.

  1. // Get the first event in the user's event list
  2. $event = $eventFeed[0];
  3.
  4. // Change the title to a new value
  5. $event->title = $service->newTitle("Woof!");
  6.
  7. // Upload the changes to the server
  8. try {
  9.     $event->save();
  10. } catch (Zend_Gdata_App_Exception $e) {
  11.     echo "Error: " . $e->getMessage();
  12. }

Deleting Events

Calendar events can be deleted either by calling the calendar service's delete() method and providing the edit URL of an event or by calling an existing event's own delete() method.

In either case, the deleted event will still show up on a user's private event feed if an updateMin query parameter is provided. Deleted events can be distinguished from regular events because they will have their eventStatus property set to "http://schemas.google.com/g/2005#event.canceled".

  1. // Option 1: Events can be deleted directly
  2. $event->delete();
  1. // Option 2: Events can be deleted supplying the edit URL of the event
  2. // to the calendar service, if known
  3. $service->delete($event->getEditLink()->href);

Accessing Event Comments

When using the full event view, comments are not directly stored within an entry. Instead, each event contains a URL to its associated comment feed which must be manually requested.

Working with comments is fundamentally similar to working with events, with the only significant difference being that a different feed and event class should be used and that the additional meta-data for events such as where and when does not exist for comments. Specifically, the comment's author is stored in the author property, and the comment text is stored in the content property.

  1. // Extract the comment URL from the first event in a user's feed list
  2. $event = $eventFeed[0];
  3. $commentUrl = $event->comments->feedLink->url;
  4.
  5. // Retrieve the comment list for the event
  6. try {
  7. $commentFeed = $service->getFeed($commentUrl);
  8. } catch (Zend_Gdata_App_Exception $e) {
  9.     echo "Error: " . $e->getMessage();
  10. }
  11.
  12. // Output each comment as an HTML list
  13. echo "<ul>";
  14. foreach ($commentFeed as $comment) {
  15.     echo "<li><em>Comment By: " . $comment->author->name "</em><br/>" .
  16.          $comment->content . "</li>";
  17. }
  18. echo "</ul>";
Authenticating with ClientLogin
Zend_Gdata
Zend Framework手册 中文版
Using Google Documents List Data API
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Gdata
  • Introduction
  • Authenticating with AuthSub
  • Using the Book Search Data API
  • Authenticating with ClientLogin
  • Using Google Calendar
  • Using Google Documents List Data API
  • Using Google Health
  • Using Google Spreadsheets
  • Using Google Apps Provisioning
  • Using Google Base
  • Using Picasa Web Albums
  • Using the YouTube Data API
  • Catching Gdata Exceptions


Using Google Documents List Data API - Zend Framework Manual

Using Google Calendar
Zend_Gdata
Zend Framework手册 中文版
Using Google Health

Using Google Documents List Data API

The Google Documents List Data API allows client applications to upload documents to Google Documents and list them in the form of Google Data API ("GData") feeds. Your client application can request a list of a user's documents, and query the content in an existing document.

See » http://code.google.com/apis/documents/overview.html for more information about the Google Documents List API.

Get a List of Documents

You can get a list of the Google Documents for a particular user by using the getDocumentListFeed() method of the docs service. The service will return a Zend_Gdata_Docs_DocumentListFeed object containing a list of documents associated with the authenticated user.

  1. $service = Zend_Gdata_Docs::AUTH_SERVICE_NAME;
  2. $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
  3. $docs = new Zend_Gdata_Docs($client);
  4. $feed = $docs->getDocumentListFeed();

The resulting Zend_Gdata_Docs_DocumentListFeed object represents the response from the server. This feed contains a list of Zend_Gdata_Docs_DocumentListEntry objects ($feed->entries), each of which represents a single Google Document.

Upload a Document

You can create a new Google Document by uploading a word processing document, spreadsheet, or presentation. This example is from the interactive Docs.php sample which comes with the library. It demonstrates uploading a file and printing information about the result from the server.

  1. /**
  2. * Upload the specified document
  3. *
  4. * @param Zend_Gdata_Docs $docs The service object to use for communicating
  5. *     with the Google Documents server.
  6. * @param boolean $html True if output should be formatted for display in a
  7. *     web browser.
  8. * @param string $originalFileName The name of the file to be uploaded. The
  9. *     MIME type of the file is determined from the extension on this file
  10. *     name. For example, test.csv is uploaded as a comma separated volume
  11. *     and converted into a spreadsheet.
  12. * @param string $temporaryFileLocation (optional) The file in which the
  13. *     data for the document is stored. This is used when the file has been
  14. *     uploaded from the client's machine to the server and is stored in
  15. *     a temporary file which does not have an extension. If this parameter
  16. *     is null, the file is read from the originalFileName.
  17. */
  18. function uploadDocument($docs, $html, $originalFileName,
  19.                         $temporaryFileLocation) {
  20.   $fileToUpload = $originalFileName;
  21.   if ($temporaryFileLocation) {
  22.     $fileToUpload = $temporaryFileLocation;
  23.   }
  24.
  25.   // Upload the file and convert it into a Google Document. The original
  26.   // file name is used as the title of the document and the MIME type
  27.   // is determined based on the extension on the original file name.
  28.   $newDocumentEntry = $docs->uploadFile($fileToUpload, $originalFileName,
  29.       null, Zend_Gdata_Docs::DOCUMENTS_LIST_FEED_URI);
  30.
  31.   echo "New Document Title: ";
  32.
  33.   if ($html) {
  34.       // Find the URL of the HTML view of this document.
  35.       $alternateLink = '';
  36.       foreach ($newDocumentEntry->link as $link) {
  37.           if ($link->getRel() === 'alternate') {
  38.               $alternateLink = $link->getHref();
  39.           }
  40.       }
  41.       // Make the title link to the document on docs.google.com.
  42.       echo "<a href=\"$alternateLink\">\n";
  43.   }
  44.   echo $newDocumentEntry->title."\n";
  45.   if ($html) {echo "</a>\n";}
  46. }

Searching the documents feed

You can search the Document List using some of the » standard Google Data API query parameters. Categories are used to restrict the type of document (word processor document, spreadsheet) returned. The full-text query string is used to search the content of all the documents. More detailed information on parameters specific to the Documents List can be found in the » Documents List Data API Reference Guide.

Get a List of Word Processing Documents

You can also request a feed containing all of your documents of a specific type. For example, to see a list of your work processing documents, you would perform a category query as follows.

  1. $feed = $docs->getDocumentListFeed(
  2.     'http://docs.google.com/feeds/documents/private/full/-/document');

Get a List of Spreadsheets

To request a list of your Google Spreadsheets, use the following category query:

  1. $feed = $docs->getDocumentListFeed(
  2.     'http://docs.google.com/feeds/documents/private/full/-/spreadsheet');

Performing a text query

You can search the content of documents by using a Zend_Gdata_Docs_Query in your request. A Query object can be used to construct the query URI, with the search term being passed in as a parameter. Here is an example method which queries the documents list for documents which contain the search string:

  1. $docsQuery = new Zend_Gdata_Docs_Query();
  2. $docsQuery->setQuery($query);
  3. $feed = $client->getDocumentListFeed($docsQuery);
Using Google Calendar
Zend_Gdata
Zend Framework手册 中文版
Using Google Health
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Gdata
  • Introduction
  • Authenticating with AuthSub
  • Using the Book Search Data API
  • Authenticating with ClientLogin
  • Using Google Calendar
  • Using Google Documents List Data API
  • Using Google Health
  • Using Google Spreadsheets
  • Using Google Apps Provisioning
  • Using Google Base
  • Using Picasa Web Albums
  • Using the YouTube Data API
  • Catching Gdata Exceptions


Using Google Health - Zend Framework Manual

Using Google Documents List Data API
Zend_Gdata
Zend Framework手册 中文版
Using Google Spreadsheets

Using Google Health

The Google Health Data API is designed to enable developers to do two things:

  • Read a user's Google Health profile or query for medical records that match particular criteria and then use the results to provide personalized functionality based on the data.

  • Add new medical records to a user's profile by including CCR data when sending a notice to a user's profile. Note: The CCR data is stored as an XML blob within the <atom> entry. The library does not provide direct accessors to the object model but it does have helpers for extracting specific fields.

There are three main feeds, each of which requires authentication. Unlike other Google Data APIs, each Google Health feed has a limited set of HTTP operations you can perform on it, depending on which authentication method you are using (ClientLogin or AuthSub/OAuth). For a list of permitted operations, see » http://code.google.com/apis/health/reference.html#Authentication.

  • Profile Feed use the profile feed to query a user's health profile for specific information.

  • Register Feed use the register feed to reconcile new CCR data into a profile.

  • Profile List Feed the profile list feed should be used to determine which of the user's Health profiles to interact with. This feed is only available when using ClientLogin.

See » http://code.google.com/apis/health for more information about the Google Health API.

Connect To The Health Service

The Google Health API, like all Google Data APIs, is based off of the Atom Publishing Protocol (APP), an XML based format for managing web-based resources. Traffic between a client and the Google Health servers occurs over HTTP and allows for authenticated connections.

Before any transactions can occur, a connection needs to be made. Creating a connection to the Health servers involves two steps: creating an HTTP client and binding a Zend_Gdata_Health service instance to that client.

Authentication

The Google Health API allows programmatic access to a user's Health profile. There are three authentication schemes that are supported by Google Health:

  • ClientLogin provides direct username/password authentication to the Health servers. Since this method requires that users provide your application with their password, this authentication scheme is only recommended for installed/desktop applications.

  • AuthSub allows a user to authorize the sharing of their private data. This provides the same level of convenience as ClientLogin but without the security risk, making it an ideal choice for web-based applications. For Google Health, AuthSub must be used in registered and secure mode--meaning that all requests to the API must be digitally signed.

  • OAuth is an alternative to AuthSub. Although this authentication scheme is not discussed in this document, more information can be found in the » Health Data API Developer's Guide.

See » Authentication Overview in the Google Data API documentation for more information on each authentication method.

Create A Health Service Instance

In order to interact with Google Health, the client library provides the Zend_Gdata_Health service class. This class provides a common interface to the Google Data and Atom Publishing Protocol models and assists in marshaling requests to and from the Health API.

Once you've decided on an authentication scheme, the next step is to create an instance of Zend_Gdata_Health . This class should be passed an instance of Zend_Gdata_HttpClient. This provides an interface for AuthSub/OAuth and ClientLogin to create a special authenticated HTTP client.

To test against the H9 Developer's (/h9) instead of Google Health (/health), the Zend_Gdata_Health constructor takes an optional third argument for you to specify the H9 service name 'weaver'.

The example below shows how to create a Health service class using ClientLogin authentication:

  1. // Parameters for ClientLogin authentication
  2. $healthServiceName = Zend_Gdata_Health::HEALTH_SERVICE_NAME;
  3. //$h9ServiceName = Zend_Gdata_Health::H9_SANDBOX_SERVICE_NAME;
  4. $user = "user@gmail.com";
  5. $pass = "pa$$w0rd";
  6.
  7. // Create an authenticated HTTP client
  8. $client = Zend_Gdata_ClientLogin::getHttpClient($user,
  9.                                                 $pass,
  10.                                                 $healthServiceName);
  11.
  12. // Create an instance of the Health service
  13. $service = new Zend_Gdata_Health($client);

A Health service using AuthSub can be created in a similar, though slightly more lengthy fashion. AuthSub is the recommend interface to communicate with Google Health because each token is directly linked to a specific profile in the user's account. Unlike other Google Data APIs, it is required that all requests from your application be digitally signed.

  1. /*
  2. * Retrieve the current URL so that the AuthSub server knows where to
  3. * redirect the user after authentication is complete.
  4. */
  5. function getCurrentUrl() {
  6.     $phpRequestUri = htmlentities(substr($_SERVER['REQUEST_URI'],
  7.                                          0,
  8.                                          strcspn($_SERVER['REQUEST_URI'],
  9.                                                  "\n\r")),
  10.                                   ENT_QUOTES);
  11.
  12.     if (isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on') {
  13.         $protocol = 'https://';
  14.     } else {
  15.         $protocol = 'http://';
  16.     }
  17.     $host = $_SERVER['HTTP_HOST'];
  18.     if ($_SERVER['SERVER_PORT'] != '' &&
  19.        (($protocol == 'http://' && $_SERVER['SERVER_PORT'] != '80') ||
  20.        ($protocol == 'https://' && $_SERVER['SERVER_PORT'] != '443'))) {
  21.         $port = ':' . $_SERVER['SERVER_PORT'];
  22.     } else {
  23.         $port = '';
  24.     }
  25.     return $protocol . $host . $port . $phpRequestUri;
  26. }
  27.
  28. /*
  29. * Redirect a user to AuthSub if they do not have a valid session token.
  30. * If they're coming back from AuthSub with a single-use token, instantiate
  31. * a new HTTP client and exchange the token for a long-lived session token
  32. * instead.
  33. */
  34. function setupClient($singleUseToken = null) {
  35.     $client = null;
  36.
  37.     // Fetch a new AuthSub token?
  38.     if (!$singleUseToken) {
  39.         $next = getCurrentUrl();
  40.         $scope = 'https://www.google.com/health/feeds';
  41.         $authSubHandler = 'https://www.google.com/health/authsub';
  42.         $secure = 1;
  43.         $session = 1;
  44.         $authSubURL =  Zend_Gdata_AuthSub::getAuthSubTokenUri($next,
  45.                                                               $scope,
  46.                                                               $secure,
  47.                                                               $session,
  48.                                                               $authSubHandler);
  49.
  50.          // 1 - allows posting notices && allows reading profile data
  51.         $permission = 1;
  52.         $authSubURL .= '&permission=' . $permission;
  53.
  54.         echo '<a href="' . $authSubURL . '">Your Google Health Account</a>';
  55.     } else {
  56.         $client = new Zend_Gdata_HttpClient();
  57.
  58.         // This sets your private key to be used to sign subsequent requests
  59.         $client->setAuthSubPrivateKeyFile('/path/to/your/rsa_private_key.pem',
  60.                                           null,
  61.                                           true);
  62.
  63.         $sessionToken =
  64.             Zend_Gdata_AuthSub::getAuthSubSessionToken(trim($singleUseToken),
  65.                                                        $client);
  66.
  67.         // Set the long-lived session token for subsequent requests
  68.         $client->setAuthSubToken($sessionToken);
  69.     }
  70.     return $client;
  71. }
  72.
  73. // -> Script execution begins here <-
  74.
  75. session_start();
  76.
  77. $client = setupClient(@$_GET['token']);
  78.
  79. // Create an instance of the Health service
  80. $userH9Sandbox = false;
  81. $healthService = new Zend_Gdata_Health($client,
  82.                                        'googleInc-MyTestAppName-v1.0',
  83.                                        $userH9Sandbox);

NOTE: the remainder of this document will assume you are using AuthSub for authentication.

Profile Feed

To query the user's profile feed, make sure your initial AuthSub token was requested with the permission=1 parameter set. The process of extracting data from the profile requires two steps, sending a query and iterating through the resulting feed.

Send a Structured Query

You can send structured queries to retrieve specific records from a user's profile.

When retrieving the profile using the Health API, specifically constructed query URLs are used to describe what (CCR) data should be returned. The Zend_Gdata_Health_Query class helps simplify this task by automatically constructing a query URL based on the parameters you set.

Query The Feed

To execute a query against the profile feed, invoke a new instance of an Zend_Gdata_Health_Query and call the service's getHealthProfileFeed() method:

  1. $healthService = new Zend_Gdata_Health($client);
  2.
  3. // example query for the top 10 medications with 2 items each
  4. $query = new Zend_Gdata_Health_Query();
  5. $query->setDigest("true");
  6. $query->setGrouped("true");
  7. $query->setMaxResultsGroup(10);
  8. $query->setMaxResultsInGroup(2);
  9. $query->setCategory("medication");
  10.
  11. $profileFeed = $healthService->getHealthProfileFeed($query);

Using setDigest("true") returns all of user's CCR data in a single Atom <entry>.

The setCategory() helper can be passed an additional parameter to return more specific CCR information. For example, to return just the medication Lipitor, use setCategory("medication", "Lipitor"). The same methodology can be applied to other categories such as conditions, allergies, lab results, etc.

A full list of supported query parameters is available in the » query parameters section of the Health API Reference Guide.

Iterate Through The Profile Entries

Each Google Health entry contains CCR data, however, using the digest=true query parameter will consolidate all of the CCR elements (that match your query) into a single Atom <entry>.

To retrieve the full CCR information from an entry, make a call to the Zend_Gdata_Health_ProfileEntry class's getCcr() method. That returns a Zend_Gdata_Health_Extension_CCR:

  1. $entries = $profileFeed->getEntries();
  2. foreach ($entries as $entry) {
  3.     $medications = $entry->getCcr()->getMedications();
  4.     //$conditions = $entry->getCcr()->getConditions();
  5.     //$immunizations = $entry->getCcr()->getImmunizations();
  6.
  7.     // print the CCR xml (this will just be the entry's medications)
  8.     foreach ($medications as $med) {
  9.         $xmlStr = $med->ownerDocument->saveXML($med);
  10.         echo "<pre>" . $xmlStr . "</pre>";
  11.     }
  12. }

Here, the getCcr() method is used in conjunction with a magic helper to drill down and extract just the medication data from the entry's CCR. The formentioned magic helper takes the form getCATEGORYNAME(), where CATEGORYNAME is a supported Google Health category. See the » Google Health reference Guide for the possible categories.

To be more efficient, you can also use category queries to only return the necessary CCR from the Google Health servers. Then, iterate through those results:

  1. $query = new Zend_Gdata_Health_Query();
  2. $query->setDigest("true");
  3. $query->setCategory("condition");
  4. $profileFeed = $healthService->getHealthProfileFeed($query);
  5.
  6. // Since the query contained digest=true, only one Atom entry is returned
  7. $entry = $profileFeed->entry[0];
  8. $conditions = $entry->getCcr()->getConditions();
  9.
  10. // print the CCR xml (this will just be the profile's conditions)
  11. foreach ($conditions as $cond) {
  12.     $xmlStr = $cond->ownerDocument->saveXML($cond);
  13.     echo "<pre>" . $xmlStr . "</pre>";
  14. }

Profile List Feed

NOTE: This feed is only available when using ClientLogin

Since ClientLogin requires a profile ID with each of its feeds, applications will likely want to query this feed first in order to select the appropriate profile. The profile list feed returns Atom entries corresponding each profile in the user's Google Health account. The profile ID is returned in the Atom <content> and the profile name in the <title> element.

Query The Feed

To execute a query against the profile list feed, call the service's getHealthProfileListFeed() method:

  1. $client = Zend_Gdata_ClientLogin::getHttpClient('user@gmail.com',
  2.                                                 'pa$$word',
  3.                                                 'health');
  4. $healthService = new Zend_Gdata_Health($client);
  5. $feed = $healthService->getHealthProfileListFeed();
  6.
  7. // print each profile's name and id
  8. $entries = $feed->getEntries();
  9. foreach ($entries as $entry) {
  10.     echo '<p>Profile name: ' . $entry->getProfileName() . '<br>';
  11.     echo 'profile ID: ' . $entry->getProfileID() . '</p>';
  12. }

Once you've determined which profile to use, call setProfileID() with the profileID as an argument. This will restrict subsequent API requests to be against that particular profile:

  1. // use the first profile
  2. $profileID = $feed->entry[0]->getProfileID();
  3. $healthService->setProfileID($profileID);
  4.
  5. $profileFeed = $healthService->getHealthProfileFeed();
  6.
  7. $profileID = $healthService->getProfileID();
  8. echo '<p><b>Queried profileID</b>: ' . $profileID . '</p>';

Sending Notices to the Register Feed

Individual posts to the register feed are known as notices. Notice are sent from third-party applications to inform the user of a new event. With AuthSub/OAuth, notices are the single means by which your application can add new CCR information into a user's profile. Notices can contain plain text (including certain XHTML elements), a CCR document, or both. As an example, notices might be sent to remind users to pick up a prescription, or they might contain lab results in the CCR format.

Sending a notice

Notices can be sent by using the sendHealthNotice() method for the Health service:

  1. $healthService = new Zend_Gdata_Health($client);
  2.
  3. $subject = "Title of your notice goes here";
  4. $body = "Notice body can contain <b>html</b> entities";
  5. $ccr = '<ContinuityOfCareRecord xmlns="urn:astm-org:CCR">
  6.   <Body>
  7.    <Problems>
  8.     <Problem>
  9.       <DateTime>
  10.         <Type><Text>Start date</Text></Type>
  11.         <ExactDateTime>2007-04-04T07:00:00Z</ExactDateTime>
  12.       </DateTime>
  13.       <Description>
  14.         <Text>Aortic valve disorders</Text>
  15.         <Code>
  16.           <Value>410.10</Value>
  17.           <CodingSystem>ICD9</CodingSystem>
  18.           <Version>2004</Version>
  19.         </Code>
  20.       </Description>
  21.       <Status><Text>Active</Text></Status>
  22.     </Problem>
  23.   </Problems>
  24.   </Body>
  25. </ContinuityOfCareRecord>';
  26.
  27. $responseEntry = $healthService->sendHealthNotice($subject,
  28.                                                   $body,
  29.                                                   "html",
  30.                                                   $ccr);
Using Google Documents List Data API
Zend_Gdata
Zend Framework手册 中文版
Using Google Spreadsheets
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Gdata
  • Introduction
  • Authenticating with AuthSub
  • Using the Book Search Data API
  • Authenticating with ClientLogin
  • Using Google Calendar
  • Using Google Documents List Data API
  • Using Google Health
  • Using Google Spreadsheets
  • Using Google Apps Provisioning
  • Using Google Base
  • Using Picasa Web Albums
  • Using the YouTube Data API
  • Catching Gdata Exceptions


Using Google Spreadsheets - Zend Framework Manual

Using Google Health
Zend_Gdata
Zend Framework手册 中文版
Using Google Apps Provisioning

Using Google Spreadsheets

The Google Spreadsheets data API allows client applications to view and update Spreadsheets content in the form of Google data API feeds. Your client application can request a list of a user's spreadsheets, edit or delete content in an existing Spreadsheets worksheet, and query the content in an existing Spreadsheets worksheet.

See » http://code.google.com/apis/spreadsheets/overview.html for more information about the Google Spreadsheets API.

Create a Spreadsheet

The Spreadsheets data API does not currently provide a way to programmatically create or delete a spreadsheet.

Get a List of Spreadsheets

You can get a list of spreadsheets for a particular user by using the getSpreadsheetFeed method of the Spreadsheets service. The service will return a Zend_Gdata_Spreadsheets_SpreadsheetFeed object containing a list of spreadsheets associated with the authenticated user.

  1. $service = Zend_Gdata_Spreadsheets::AUTH_SERVICE_NAME;
  2. $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
  3. $spreadsheetService = new Zend_Gdata_Spreadsheets($client);
  4. $feed = $spreadsheetService->getSpreadsheetFeed();

Get a List of Worksheets

A given spreadsheet may contain multiple worksheets. For each spreadsheet, there's a worksheets metafeed listing all the worksheets in that spreadsheet.

Given the spreadsheet key from the <id> of a Zend_Gdata_Spreadsheets_SpreadsheetEntry object you've already retrieved, you can fetch a feed containing a list of worksheets associated with that spreadsheet.

  1. $query = new Zend_Gdata_Spreadsheets_DocumentQuery();
  2. $query->setSpreadsheetKey($spreadsheetKey);
  3. $feed = $spreadsheetService->getWorksheetFeed($query);

The resulting Zend_Gdata_Spreadsheets_WorksheetFeed object feed represents the response from the server. Among other things, this feed contains a list of Zend_Gdata_Spreadsheets_WorksheetEntry objects ($feed->entries), each of which represents a single worksheet.

Interacting With List-based Feeds

A given worksheet generally contains multiple rows, each containing multiple cells. You can request data from the worksheet either as a list-based feed, in which each entry represents a row, or as a cell-based feed, in which each entry represents a single cell. For information on cell-based feeds, see Interacting with cell-based feeds.

The following sections describe how to get a list-based feed, add a row to a worksheet, and send queries with various query parameters.

The list feed makes some assumptions about how the data is laid out in the spreadsheet.

In particular, the list feed treats the first row of the worksheet as a header row; Spreadsheets dynamically creates XML elements named after the contents of header-row cells. Users who want to provide Gdata feeds should not put any data other than column headers in the first row of a worksheet.

The list feed contains all rows after the first row up to the first blank row. The first blank row terminates the data set. If expected data isn't appearing in a feed, check the worksheet manually to see whether there's an unexpected blank row in the middle of the data. In particular, if the second row of the spreadsheet is blank, then the list feed will contain no data.

A row in a list feed is as many columns wide as the worksheet itself.

Get a List-based Feed

To retrieve a worksheet's list feed, use the getListFeed method of the Spreadsheets service.

  1. $query = new Zend_Gdata_Spreadsheets_ListQuery();
  2. $query->setSpreadsheetKey($spreadsheetKey);
  3. $query->setWorksheetId($worksheetId);
  4. $listFeed = $spreadsheetService->getListFeed($query);

The resulting Zend_Gdata_Spreadsheets_ListFeed object $listfeed represents a response from the server. Among other things, this feed contains an array of Zend_Gdata_Spreadsheets_ListEntry objects ($listFeed->entries), each of which represents a single row in a worksheet.

Each Zend_Gdata_Spreadsheets_ListEntry contains an array, custom, which contains the data for that row. You can extract and display this array:

  1. $rowData = $listFeed->entries[1]->getCustom();
  2. foreach($rowData as $customEntry) {
  3.   echo $customEntry->getColumnName() . " = " . $customEntry->getText();
  4. }

An alternate version of this array, customByName, allows direct access to an entry's cells by name. This is convenient when trying to access a specific header:

  1. $customEntry = $listFeed->entries[1]->getCustomByName('my_heading');
  2. echo $customEntry->getColumnName() . " = " . $customEntry->getText();

Reverse-sort Rows

By default, rows in the feed appear in the same order as the corresponding rows in the GUI; that is, they're in order by row number. To get rows in reverse order, set the reverse properties of the Zend_Gdata_Spreadsheets_ListQuery object to TRUE:

  1. $query = new Zend_Gdata_Spreadsheets_ListQuery();
  2. $query->setSpreadsheetKey($spreadsheetKey);
  3. $query->setWorksheetId($worksheetId);
  4. $query->setReverse('true');
  5. $listFeed = $spreadsheetService->getListFeed($query);

Note that if you want to order (or reverse sort) by a particular column, rather than by position in the worksheet, you can set the orderby value of the Zend_Gdata_Spreadsheets_ListQuery object to column:<the header of that column>.

Send a Structured Query

You can set a Zend_Gdata_Spreadsheets_ListQuery's sq value to produce a feed with entries that meet the specified criteria. For example, suppose you have a worksheet containing personnel data, in which each row represents information about a single person. You wish to retrieve all rows in which the person's name is "John" and the person's age is over 25. To do so, you would set sq as follows:

  1. $query = new Zend_Gdata_Spreadsheets_ListQuery();
  2. $query->setSpreadsheetKey($spreadsheetKey);
  3. $query->setWorksheetId($worksheetId);
  4. $query->setSpreadsheetQuery('name=John and age>25');
  5. $listFeed = $spreadsheetService->getListFeed($query);

Add a Row

Rows can be added to a spreadsheet by using the insertRow method of the Spreadsheet service.

  1. $insertedListEntry = $spreadsheetService->insertRow($rowData,
  2.                                                     $spreadsheetKey,
  3.                                                     $worksheetId);

The $rowData parameter contains an array of column keys to data values. The method returns a Zend_Gdata_Spreadsheets_SpreadsheetsEntry object which represents the inserted row.

Spreadsheets inserts the new row immediately after the last row that appears in the list-based feed, which is to say immediately before the first entirely blank row.

Edit a Row

Once a Zend_Gdata_Spreadsheets_ListEntry object is fetched, its rows can be updated by using the updateRow method of the Spreadsheet service.

  1. $updatedListEntry = $spreadsheetService->updateRow($oldListEntry,
  2.                                                    $newRowData);

The $oldListEntry parameter contains the list entry to be updated. $newRowData contains an array of column keys to data values, to be used as the new row data. The method returns a Zend_Gdata_Spreadsheets_SpreadsheetsEntry object which represents the updated row.

Delete a Row

To delete a row, simply invoke deleteRow on the Zend_Gdata_Spreadsheets object with the existing entry to be deleted:

  1. $spreadsheetService->deleteRow($listEntry);

Alternatively, you can call the delete method of the entry itself:

  1. $listEntry->delete();

Interacting With Cell-based Feeds

In a cell-based feed, each entry represents a single cell.

Note that we don't recommend interacting with both a cell-based feed and a list-based feed for the same worksheet at the same time.

Get a Cell-based Feed

To retrieve a worksheet's cell feed, use the getCellFeed method of the Spreadsheets service.

  1. $query = new Zend_Gdata_Spreadsheets_CellQuery();
  2. $query->setSpreadsheetKey($spreadsheetKey);
  3. $query->setWorksheetId($worksheetId);
  4. $cellFeed = $spreadsheetService->getCellFeed($query);

The resulting Zend_Gdata_Spreadsheets_CellFeed object $cellFeed represents a response from the server. Among other things, this feed contains an array of Zend_Gdata_Spreadsheets_CellEntry objects ($cellFeed>entries), each of which represents a single cell in a worksheet. You can display this information:

  1. foreach($cellFeed as $cellEntry) {
  2.   $row = $cellEntry->cell->getRow();
  3.   $col = $cellEntry->cell->getColumn();
  4.   $val = $cellEntry->cell->getText();
  5.   echo "$row, $col = $val\n";
  6. }

Send a Cell Range Query

Suppose you wanted to retrieve the cells in the first column of a worksheet. You can request a cell feed containing only this column as follows:

  1. $query = new Zend_Gdata_Spreadsheets_CellQuery();
  2. $query->setMinCol(1);
  3. $query->setMaxCol(1);
  4. $query->setMinRow(2);
  5. $feed = $spreadsheetService->getCellsFeed($query);

This requests all the data in column 1, starting with row 2.

Change Contents of a Cell

To modify the contents of a cell, call updateCell with the row, column, and new value of the cell.

  1. $updatedCell = $spreadsheetService->updateCell($row,
  2.                                                $col,
  3.                                                $inputValue,
  4.                                                $spreadsheetKey,
  5.                                                $worksheetId);

The new data is placed in the specified cell in the worksheet. If the specified cell contains data already, it will be overwritten. Note: Use updateCell to change the data in a cell, even if the cell is empty.

Using Google Health
Zend_Gdata
Zend Framework手册 中文版
Using Google Apps Provisioning
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Gdata
  • Introduction
  • Authenticating with AuthSub
  • Using the Book Search Data API
  • Authenticating with ClientLogin
  • Using Google Calendar
  • Using Google Documents List Data API
  • Using Google Health
  • Using Google Spreadsheets
  • Using Google Apps Provisioning
  • Using Google Base
  • Using Picasa Web Albums
  • Using the YouTube Data API
  • Catching Gdata Exceptions


Using Google Apps Provisioning - Zend Framework Manual

Using Google Spreadsheets
Zend_Gdata
Zend Framework手册 中文版
Using Google Base

Using Google Apps Provisioning

Google Apps is a service which allows domain administrators to offer their users managed access to Google services such as Mail, Calendar, and Docs & Spreadsheets. The Provisioning API offers a programmatic interface to configure this service. Specifically, this API allows administrators the ability to create, retrieve, update, and delete user accounts, nicknames, and email lists.

This library implements version 2.0 of the Provisioning API. Access to your account via the Provisioning API must be manually enabled for each domain using the Google Apps control panel. Only certain account types are able to enable this feature.

For more information on the Google Apps Provisioning API, including instructions for enabling API access, refer to the » Provisioning API V2.0 Reference.

Note: Authentication
 The Provisioning API does not support authentication via AuthSub and anonymous access is not permitted. All HTTP connections must be authenticated using ClientAuth authentication.

Setting the current domain

In order to use the Provisioning API, the domain being administered needs to be specified in all request URIs. In order to ease development, this information is stored within both the Gapps service and query classes to use when constructing requests.

Setting the domain for the service class

To set the domain for requests made by the service class, either call setDomain() or specify the domain when instantiating the service class. For example:

  1. $domain = "example.com";
  2. $gdata = new Zend_Gdata_Gapps($client, $domain);

Setting the domain for query classes

Setting the domain for requests made by query classes is similar to setting it for the service class-either call setDomain() or specify the domain when creating the query. For example:

  1. $domain = "example.com";
  2. $query = new Zend_Gdata_Gapps_UserQuery($domain, $arg);

When using a service class factory method to create a query, the service class will automatically set the query's domain to match its own domain. As a result, it is not necessary to specify the domain as part of the constructor arguments.

  1. $domain = "example.com";
  2. $gdata = new Zend_Gdata_Gapps($client, $domain);
  3. $query = $gdata->newUserQuery($arg);

Interacting with users

Each user account on a Google Apps hosted domain is represented as an instance of Zend_Gdata_Gapps_UserEntry. This class provides access to all account properties including name, username, password, access rights, and current quota.

Creating a user account

User accounts can be created by calling the createUser() convenience method:

  1. $gdata->createUser('foo', 'Random', 'User', '••••••••');

Users can also be created by instantiating UserEntry, providing a username, given name, family name, and password, then calling insertUser() on a service object to upload the entry to the server.

  1. $user = $gdata->newUserEntry();
  2. $user->login = $gdata->newLogin();
  3. $user->login->username = 'foo';
  4. $user->login->password = '••••••••';
  5. $user->name = $gdata->newName();
  6. $user->name->givenName = 'Random';
  7. $user->name->familyName = 'User';
  8. $user = $gdata->insertUser($user);

The user's password should normally be provided as cleartext. Optionally, the password can be provided as an SHA-1 digest if login->passwordHashFunction is set to 'SHA-1'.

Retrieving a user account

Individual user accounts can be retrieved by calling the retrieveUser() convenience method. If the user is not found, NULL will be returned.

  1. $user = $gdata->retrieveUser('foo');
  2.
  3. echo 'Username: ' . $user->login->userName . "\n";
  4. echo 'Given Name: ' . $user->name->givenName . "\n";
  5. echo 'Family Name: ' . $user->name->familyName . "\n";
  6. echo 'Suspended: ' . ($user->login->suspended ? 'Yes' : 'No') . "\n";
  7. echo 'Admin: ' . ($user->login->admin ? 'Yes' : 'No') . "\n"
  8. echo 'Must Change Password: ' .
  9.      ($user->login->changePasswordAtNextLogin ? 'Yes' : 'No') . "\n";
  10. echo 'Has Agreed To Terms: ' .
  11.      ($user->login->agreedToTerms ? 'Yes' : 'No') . "\n";

Users can also be retrieved by creating an instance of Zend_Gdata_Gapps_UserQuery, setting its username property to equal the username of the user that is to be retrieved, and calling getUserEntry() on a service object with that query.

  1. $query = $gdata->newUserQuery('foo');
  2. $user = $gdata->getUserEntry($query);
  3.
  4. echo 'Username: ' . $user->login->userName . "\n";
  5. echo 'Given Name: ' . $user->login->givenName . "\n";
  6. echo 'Family Name: ' . $user->login->familyName . "\n";
  7. echo 'Suspended: ' . ($user->login->suspended ? 'Yes' : 'No') . "\n";
  8. echo 'Admin: ' . ($user->login->admin ? 'Yes' : 'No') . "\n"
  9. echo 'Must Change Password: ' .
  10.      ($user->login->changePasswordAtNextLogin ? 'Yes' : 'No') . "\n";
  11. echo 'Has Agreed To Terms: ' .
  12.      ($user->login->agreedToTerms ? 'Yes' : 'No') . "\n";

If the specified user cannot be located a ServiceException will be thrown with an error code of Zend_Gdata_Gapps_Error::ENTITY_DOES_NOT_EXIST. ServiceExceptions will be covered in Handling errors.

Retrieving all users in a domain

To retrieve all users in a domain, call the retrieveAllUsers() convenience method.

  1. $feed = $gdata->retrieveAllUsers();
  2.
  3. foreach ($feed as $user) {
  4.     echo "  * " . $user->login->username . ' (' . $user->name->givenName .
  5.         ' ' . $user->name->familyName . ")\n";
  6. }

This will create a Zend_Gdata_Gapps_UserFeed object which holds each user on the domain.

Alternatively, call getUserFeed() with no options. Keep in mind that on larger domains this feed may be paged by the server. For more information on paging, see Working with Multi-page Feeds.

  1. $feed = $gdata->getUserFeed();
  2.
  3. foreach ($feed as $user) {
  4.     echo "  * " . $user->login->username . ' (' . $user->name->givenName .
  5.         ' ' . $user->name->familyName . ")\n";
  6. }

Updating a user account

The easiest way to update a user account is to retrieve the user as described in the previous sections, make any desired changes, then call save() on that user. Any changes made will be propagated to the server.

  1. $user = $gdata->retrieveUser('foo');
  2. $user->name->givenName = 'Foo';
  3. $user->name->familyName = 'Bar';
  4. $user = $user->save();

Resetting a user's password

A user's password can be reset to a new value by updating the login->password property.

  1. $user = $gdata->retrieveUser('foo');
  2. $user->login->password = '••••••••';
  3. $user = $user->save();

Note that it is not possible to recover a password in this manner as stored passwords are not made available via the Provisioning API for security reasons.

Forcing a user to change their password

A user can be forced to change their password at their next login by setting the login->changePasswordAtNextLogin property to TRUE.

  1. $user = $gdata->retrieveUser('foo');
  2. $user->login->changePasswordAtNextLogin = true;
  3. $user = $user->save();

Similarly, this can be undone by setting the login->changePasswordAtNextLogin property to FALSE.

Suspending a user account

Users can be restricted from logging in without deleting their user account by instead suspending their user account. Accounts can be suspended or restored by using the suspendUser() and restoreUser() convenience methods:

  1. $gdata->suspendUser('foo');
  2. $gdata->restoreUser('foo');

Alternatively, you can set the UserEntry's login->suspended property to TRUE.

  1. $user = $gdata->retrieveUser('foo');
  2. $user->login->suspended = true;
  3. $user = $user->save();

To restore the user's access, set the login->suspended property to FALSE.

Granting administrative rights

Users can be granted the ability to administer your domain by setting their login->admin property to TRUE.

  1. $user = $gdata->retrieveUser('foo');
  2. $user->login->admin = true;
  3. $user = $user->save();

And as expected, setting a user's login->admin property to FALSE revokes their administrative rights.

Deleting user accounts

Deleting a user account to which you already hold a UserEntry is a simple as calling delete() on that entry.

  1. $user = $gdata->retrieveUser('foo');
  2. $user->delete();

If you do not have access to a UserEntry object for an account, use the deleteUser() convenience method.

  1. $gdata->deleteUser('foo');

Interacting with nicknames

Nicknames serve as email aliases for existing users. Each nickname contains precisely two key properties: its name and its owner. Any email addressed to a nickname is forwarded to the user who owns that nickname.

Nicknames are represented as an instances of Zend_Gdata_Gapps_NicknameEntry.

Creating a nickname

Nicknames can be created by calling the createNickname() convenience method:

  1. $gdata->createNickname('foo', 'bar');

Nicknames can also be created by instantiating NicknameEntry, providing the nickname with a name and an owner, then calling insertNickname() on a service object to upload the entry to the server.

  1. $nickname = $gdata->newNicknameEntry();
  2. $nickname->login = $gdata->newLogin('foo');
  3. $nickname->nickname = $gdata->newNickname('bar');
  4. $nickname = $gdata->insertNickname($nickname);

Retrieving a nickname

Nicknames can be retrieved by calling the retrieveNickname() convenience method. This will return NULL if a user is not found.

  1. $nickname = $gdata->retrieveNickname('bar');
  2.
  3. echo 'Nickname: ' . $nickname->nickname->name . "\n";
  4. echo 'Owner: ' . $nickname->login->username . "\n";

Individual nicknames can also be retrieved by creating an instance of Zend_Gdata_Gapps_NicknameQuery, setting its nickname property to equal the nickname that is to be retrieved, and calling getNicknameEntry() on a service object with that query.

  1. $query = $gdata->newNicknameQuery('bar');
  2. $nickname = $gdata->getNicknameEntry($query);
  3.
  4. echo 'Nickname: ' . $nickname->nickname->name . "\n";
  5. echo 'Owner: ' . $nickname->login->username . "\n";

As with users, if no corresponding nickname is found a ServiceException will be thrown with an error code of Zend_Gdata_Gapps_Error::ENTITY_DOES_NOT_EXIST. Again, these will be discussed in Handling errors.

Retrieving all nicknames for a user

To retrieve all nicknames associated with a given user, call the convenience method retrieveNicknames().

  1. $feed = $gdata->retrieveNicknames('foo');
  2.
  3. foreach ($feed as $nickname) {
  4.     echo '  * ' . $nickname->nickname->name . "\n";
  5. }

This will create a Zend_Gdata_Gapps_NicknameFeed object which holds each nickname associated with the specified user.

Alternatively, create a new Zend_Gdata_Gapps_NicknameQuery, set its username property to the desired user, and submit the query by calling getNicknameFeed() on a service object.

  1. $query = $gdata->newNicknameQuery();
  2. $query->setUsername('foo');
  3. $feed = $gdata->getNicknameFeed($query);
  4.
  5. foreach ($feed as $nickname) {
  6.     echo '  * ' . $nickname->nickname->name . "\n";
  7. }

Retrieving all nicknames in a domain

To retrieve all nicknames in a feed, simply call the convenience method retrieveAllNicknames()

  1. $feed = $gdata->retrieveAllNicknames();
  2.
  3. foreach ($feed as $nickname) {
  4.     echo '  * ' . $nickname->nickname->name . ' => ' .
  5.         $nickname->login->username . "\n";
  6. }

This will create a Zend_Gdata_Gapps_NicknameFeed object which holds each nickname on the domain.

Alternatively, call getNicknameFeed() on a service object with no arguments.

  1. $feed = $gdata->getNicknameFeed();
  2.
  3. foreach ($feed as $nickname) {
  4.     echo '  * ' . $nickname->nickname->name . ' => ' .
  5.         $nickname->login->username . "\n";
  6. }

Deleting a nickname

Deleting a nickname to which you already hold a NicknameEntry for is a simple as calling delete() on that entry.

  1. $nickname = $gdata->retrieveNickname('bar');
  2. $nickname->delete();

For nicknames which you do not hold a NicknameEntry for, use the deleteNickname() convenience method.

  1. $gdata->deleteNickname('bar');

Interacting with email lists

Email lists allow several users to retrieve email addressed to a single email address. Users do not need to be a member of this domain in order to subscribe to an email list provided their complete email address (including domain) is used.

Each email list on a domain is represented as an instance of Zend_Gdata_Gapps_EmailListEntry.

Creating an email list

Email lists can be created by calling the createEmailList() convenience method:

  1. $gdata->createEmailList('friends');

Email lists can also be created by instantiating EmailListEntry, providing a name for the list, then calling insertEmailList() on a service object to upload the entry to the server.

  1. $list = $gdata->newEmailListEntry();
  2. $list->emailList = $gdata->newEmailList('friends');
  3. $list = $gdata->insertEmailList($list);

Retrieving all email lists to which a recipient is subscribed

To retrieve all email lists to which a particular recipient is subscribed, call the retrieveEmailLists() convenience method:

  1. $feed = $gdata->retrieveEmailLists('baz@somewhere.com');
  2.
  3. foreach ($feed as $list) {
  4.     echo '  * ' . $list->emailList->name . "\n";
  5. }

This will create a Zend_Gdata_Gapps_EmailListFeed object which holds each email list associated with the specified recipient.

Alternatively, create a new Zend_Gdata_Gapps_EmailListQuery, set its recipient property to the desired email address, and submit the query by calling getEmailListFeed() on a service object.

  1. $query = $gdata->newEmailListQuery();
  2. $query->setRecipient('baz@somewhere.com');
  3. $feed = $gdata->getEmailListFeed($query);
  4.
  5. foreach ($feed as $list) {
  6.     echo '  * ' . $list->emailList->name . "\n";
  7. }

Retrieving all email lists in a domain

To retrieve all email lists in a domain, call the convenience method retrieveAllEmailLists().

  1. $feed = $gdata->retrieveAllEmailLists();
  2.
  3. foreach ($feed as $list) {
  4.     echo '  * ' . $list->emailList->name . "\n";
  5. }

This will create a Zend_Gdata_Gapps_EmailListFeed object which holds each email list on the domain.

Alternatively, call getEmailListFeed() on a service object with no arguments.

  1. $feed = $gdata->getEmailListFeed();
  2.
  3. foreach ($feed as $list) {
  4.     echo '  * ' . $list->emailList->name . "\n";
  5. }

Deleting an email list

To delete an email list, call the deleteEmailList() convenience method:

  1. $gdata->deleteEmailList('friends');

Interacting with email list recipients

Each recipient subscribed to an email list is represented by an instance of Zend_Gdata_Gapps_EmailListRecipient. Through this class, individual recipients can be added and removed from email lists.

Adding a recipient to an email list

To add a recipient to an email list, simply call the addRecipientToEmailList() convenience method:

  1. $gdata->addRecipientToEmailList('bar@somewhere.com', 'friends');

Retrieving the list of subscribers to an email list

The convenience method retrieveAllRecipients() can be used to retrieve the list of subscribers to an email list:

  1. $feed = $gdata->retrieveAllRecipients('friends');
  2.
  3. foreach ($feed as $recipient) {
  4.     echo '  * ' . $recipient->who->email . "\n";
  5. }

Alternatively, construct a new EmailListRecipientQuery, set its emailListName property to match the desired email list, and call getEmailListRecipientFeed() on a service object.

  1. $query = $gdata->newEmailListRecipientQuery();
  2. $query->setEmailListName('friends');
  3. $feed = $gdata->getEmailListRecipientFeed($query);
  4.
  5. foreach ($feed as $recipient) {
  6.     echo '  * ' . $recipient->who->email . "\n";
  7. }

This will create a Zend_Gdata_Gapps_EmailListRecipientFeed object which holds each recipient for the selected email list.

Removing a recipient from an email list

To remove a recipient from an email list, call the removeRecipientFromEmailList() convenience method:

  1. $gdata->removeRecipientFromEmailList('baz@somewhere.com', 'friends');

Handling errors

In addition to the standard suite of exceptions thrown by Zend_Gdata, requests using the Provisioning API may also throw a Zend_Gdata_Gapps_ServiceException. These exceptions indicate that a API specific error occurred which prevents the request from completing.

Each ServiceException instance may hold one or more Error objects. Each of these objects contains an error code, reason, and (optionally) the input which triggered the exception. A complete list of known error codes is provided in the Zend Framework API documentation under Zend_Gdata_Gapps_Error. Additionally, the authoritative error list is available online at » Google Apps Provisioning API V2.0 Reference: Appendix D.

While the complete list of errors received is available within ServiceException as an array by calling getErrors(), often it is convenient to know if one specific error occurred. For these cases the presence of an error can be determined by calling hasError().

The following example demonstrates how to detect if a requested resource doesn't exist and handle the fault gracefully:

  1. function retrieveUser ($username) {
  2.     $query = $gdata->newUserQuery($username);
  3.     try {
  4.         $user = $gdata->getUserEntry($query);
  5.     } catch (Zend_Gdata_Gapps_ServiceException $e) {
  6.         // Set the user to null if not found
  7.         if ($e->hasError(Zend_Gdata_Gapps_Error::ENTITY_DOES_NOT_EXIST)) {
  8.             $user = null;
  9.         } else {
  10.             throw $e;
  11.         }
  12.     }
  13.     return $user;
  14. }
Using Google Spreadsheets
Zend_Gdata
Zend Framework手册 中文版
Using Google Base
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Gdata
  • Introduction
  • Authenticating with AuthSub
  • Using the Book Search Data API
  • Authenticating with ClientLogin
  • Using Google Calendar
  • Using Google Documents List Data API
  • Using Google Health
  • Using Google Spreadsheets
  • Using Google Apps Provisioning
  • Using Google Base
  • Using Picasa Web Albums
  • Using the YouTube Data API
  • Catching Gdata Exceptions


Using Google Base - Zend Framework Manual

Using Google Apps Provisioning
Zend_Gdata
Zend Framework手册 中文版
Using Picasa Web Albums

Using Google Base

The Google Base data API is designed to enable developers to do two things:

  • Query Google Base data to create applications and mashups.

  • Input and manage Google Base items programmatically.

There are two item feeds: snippets feed and customer items feeds. The snippets feed contains all Google Base data and is available to anyone to query against without a need for authentication. The customer items feed is a customer-specific subset of data and only a customer/owner can access this feed to insert, update, or delete their own data. Queries are constructed the same way against both types of feeds.

See » http://code.google.com/apis/base for more information about the Google Base API.

Connect To The Base Service

The Google Base API, like all GData APIs, is based off of the Atom Publishing Protocol (APP), an XML based format for managing web-based resources. Traffic between a client and the Google Base servers occurs over HTTP and allows for both authenticated and unauthenticated connections.

Before any transactions can occur, this connection needs to be made. Creating a connection to the base servers involves two steps: creating an HTTP client and binding a Zend_Gdata_Gbase service instance to that client.

Authentication

The Google Base API allows access to both public and private base feeds. Public feeds do not require authentication, but are read-only and offer reduced functionality. Private feeds offers the most complete functionality but requires an authenticated connection to the base servers. There are three authentication schemes that are supported by Google Base:

  • ClientAuth provides direct username/password authentication to the base servers. Since this scheme requires that users provide your application with their password, this authentication is only recommended when other authentication schemes are insufficient.

  • AuthSub allows authentication to the base servers via a Google proxy server. This provides the same level of convenience as ClientAuth but without the security risk, making this an ideal choice for web-based applications.

The Zend_Gdata library provides support for all three authentication schemes. The rest of this chapter will assume that you are familiar the authentication schemes available and how to create an appropriate authenticated connection. For more information, please see section Google Data Client Authentication. or the » Authentication Overview in the Google Data API Developer's Guide.

Create A Service Instance

In order to interact with Google Base, this library provides the Zend_Gdata_Gbase service class. This class provides a common interface to the Google Data and Atom Publishing Protocol models and assists in marshaling requests to and from the base servers.

Once deciding on an authentication scheme, the next step is to create an instance of Zend_Gdata_Gbase . This class takes in an instance of Zend_Http_Client as a single argument. This provides an interface for AuthSub and ClientAuth authentication, as both of these creation of a special authenticated HTTP client. If no arguments are provided, an unauthenticated instance of Zend_Http_Client will be automatically created.

The example below shows how to create a Base service class using ClientAuth authentication:

  1. // Parameters for ClientAuth authentication
  2. $service = Zend_Gdata_Gbase::AUTH_SERVICE_NAME;
  3. $user = "sample.user@gmail.com";
  4. $pass = "pa$$w0rd";
  5.
  6. // Create an authenticated HTTP client
  7. $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
  8.
  9. // Create an instance of the Base service
  10. $service = new Zend_Gdata_Gbase($client);

A Base service using AuthSub can be created in a similar, though slightly more lengthy fashion:

  1. /*
  2. * Retrieve the current URL so that the AuthSub server knows where to
  3. * redirect the user after authentication is complete.
  4. */
  5. function getCurrentUrl()
  6. {
  7.     global $_SERVER;
  8.
  9.     // Filter php_self to avoid a security vulnerability.
  10.     $php_request_uri =
  11.         htmlentities(substr($_SERVER['REQUEST_URI'],
  12.                             0,
  13.                             strcspn($_SERVER['REQUEST_URI'], "\n\r")),
  14.                      ENT_QUOTES);
  15.
  16.     if (isset($_SERVER['HTTPS']) &&
  17.         strtolower($_SERVER['HTTPS']) == 'on') {
  18.         $protocol = 'https://';
  19.     } else {
  20.         $protocol = 'http://';
  21.     }
  22.     $host = $_SERVER['HTTP_HOST'];
  23.     if ($_SERVER['HTTP_PORT'] != '' &&
  24.         (($protocol == 'http://' && $_SERVER['HTTP_PORT'] != '80') ||
  25.         ($protocol == 'https://' && $_SERVER['HTTP_PORT'] != '443'))) {
  26.         $port = ':' . $_SERVER['HTTP_PORT'];
  27.     } else {
  28.         $port = '';
  29.     }
  30.     return $protocol . $host . $port . $php_request_uri;
  31. }
  32.
  33. /**
  34. * Obtain an AuthSub authenticated HTTP client, redirecting the user
  35. * to the AuthSub server to login if necessary.
  36. */
  37. function getAuthSubHttpClient()
  38. {
  39.     global $_SESSION, $_GET;
  40.
  41.     // If there is no AuthSub session or one-time token waiting for us,
  42.     // redirect the user to the AuthSub server to get one.
  43.     if (!isset($_SESSION['sessionToken']) && !isset($_GET['token'])) {
  44.         // Parameters to give to AuthSub server
  45.         $next = getCurrentUrl();
  46.         $scope = "http://www.google.com/base/feeds/items/";
  47.         $secure = false;
  48.         $session = true;
  49.
  50.         // Redirect the user to the AuthSub server to sign in
  51.
  52.         $authSubUrl = Zend_Gdata_AuthSub::getAuthSubTokenUri($next,
  53.                                                              $scope,
  54.                                                              $secure,
  55.                                                              $session);
  56.          header("HTTP/1.0 307 Temporary redirect");
  57.
  58.          header("Location: " . $authSubUrl);
  59.
  60.          exit();
  61.     }
  62.
  63.     // Convert an AuthSub one-time token into a session token if needed
  64.     if (!isset($_SESSION['sessionToken']) && isset($_GET['token'])) {
  65.         $_SESSION['sessionToken'] =
  66.             Zend_Gdata_AuthSub::getAuthSubSessionToken($_GET['token']);
  67.     }
  68.
  69.     // At this point we are authenticated via AuthSub and can obtain an
  70.     // authenticated HTTP client instance
  71.
  72.     // Create an authenticated HTTP client
  73.     $client = Zend_Gdata_AuthSub::getHttpClient($_SESSION['sessionToken']);
  74.     return $client;
  75. }
  76.
  77. // -> Script execution begins here <-
  78.
  79. // Make sure http://code.google.com/apis/gdata/reference.html#Queriesthat
  80. // the user has a valid session, so we can record the
  81. // AuthSub session token once it is available.
  82. session_start();
  83.
  84. // Create an instance of the Base service, redirecting the user
  85. // to the AuthSub server if necessary.
  86. $service = new Zend_Gdata_Gbase(getAuthSubHttpClient());

Finally, an unauthenticated server can be created for use with snippets feeds:

  1. // Create an instance of the Base service using an unauthenticated HTTP client
  2. $service = new Zend_Gdata_Gbase();

Retrieve Items

You can query customer items feed or snippets feed to retrieve items. It involves two steps, sending a query and iterating through the returned feed.

Send a Structured Query

You can send a structured query to retrieve items from your own customer items feed or from the public snippets feed.

When retrieving items using the Base API, specially constructed query URLs are used to describe what events should be returned. The Zend_Gdata_Gbase_ItemQuery and Zend_Gdata_Gbase_SnippetQuery classes simplify this task by automatically constructing a query URL based on provided parameters.

Query Customer Items Feed

To execute a query against the customer items feed, invoke newItemQuery() and getGbaseItemFeed() methods:

  1. $service = new Zend_Gdata_Gbase($client);
  2. $query = $service->newItemQuery();
  3. $query->setBq('[title:Programming]');
  4. $query->setOrderBy('modification_time');
  5. $query->setSortOrder('descending');
  6. $query->setMaxResults('5');
  7. $feed = $service->getGbaseItemFeed($query);

A full list of these parameters is available at the » Query parameters section of the Customer Items Feed documentation.

Query Snippets Feed

To execute a query against the public snippets feed, invoke newSnippetQuery() and getGbaseSnippetFeed() methods:

  1. $service = new Zend_Gdata_Gbase();
  2. $query = $service->newSnippetQuery();
  3. $query->setBq('[title:Programming]');
  4. $query->setOrderBy('modification_time');
  5. $query->setSortOrder('descending');
  6. $query->setMaxResults('5');
  7. $feed = $service->getGbaseSnippetFeed($query);

A full list of these parameters is available at the » Query parameters section of the Snippets Feed documentation.

Iterate through the Items

Google Base items can contain item-specific attributes such as <g:main_ingredient> and <g:weight>.

To iterate through all attributes of a given item, invoke getGbaseAttributes() and iterate through the results:

  1. foreach ($feed->entries as $entry) {
  2.   // Get all attributes and print out the name and text value of each
  3.   // attribute
  4.   $baseAttributes = $entry->getGbaseAttributes();
  5.   foreach ($baseAttributes as $attr) {
  6.     echo "Attribute " . $attr->name . " : " . $attr->text . "<br>";
  7.   }
  8. }

Or, you can look for specific attribute name and iterate through the results that match:

  1. foreach ($feed->entries as $entry) {
  2.   // Print all main ingredients <g:main_ingredient>
  3.   $baseAttributes = $entry->getGbaseAttribute("main_ingredient");
  4.   foreach ($baseAttributes as $attr) {
  5.     echo "Main ingredient: " . $attr->text . "<br>";
  6.   }
  7. }

Insert, Update, and Delete Customer Items

A customer/owner can access his own Customer Items feed to insert, update, or delete their items. These operations do not apply to the public snippets feed.

You can test a feed operation before it is actually executed by setting the dry-run flag ($dryRun) to TRUE. Once you are sure that you want to submit the data, set it to FALSE to execute the operation.

Insert an Item

Items can be added by using the insertGbaseItem() method for the Base service:

  1. $service = new Zend_Gdata_Gbase($client);
  2. $newEntry = $service->newItemEntry();
  3.
  4. // Add title
  5. $title = "PHP Developer Handbook";
  6. $newEntry->title = $service->newTitle(trim($title));
  7.
  8. // Add some content
  9. $content = "Essential handbook for PHP developers.";
  10. $newEntry->content = $service->newContent($content);
  11. $newEntry->content->type = 'text';
  12.
  13. // Define product type
  14. $itemType = "Products";
  15. $newEntry->itemType = $itemType;
  16.
  17. // Add item specific attributes
  18. $newEntry->addGbaseAttribute("product_type", "book", "text");
  19. $newEntry->addGbaseAttribute("price", "12.99 USD", "floatUnit");
  20. $newEntry->addGbaseAttribute("quantity", "10", "int");
  21. $newEntry->addGbaseAttribute("weight", "2.2 lbs", "numberUnit");
  22. $newEntry->addGbaseAttribute("condition", "New", "text");
  23. $newEntry->addGbaseAttribute("author", "John Doe", "text");
  24. $newEntry->addGbaseAttribute("edition", "First Edition", "text");
  25. $newEntry->addGbaseAttribute("pages", "253", "number");
  26. $newEntry->addGbaseAttribute("publisher", "My Press", "text");
  27. $newEntry->addGbaseAttribute("year", "2007", "number");
  28. $newEntry->addGbaseAttribute("payment_accepted", "Google Checkout", "text");
  29.
  30. $dryRun = true;
  31. $createdEntry = $service->insertGbaseItem($newEntry, $dryRun);

Modify an Item

You can update each attribute element of an item as you iterate through them:

  1. // Update the title
  2. $newTitle = "PHP Developer Handbook Second Edition";
  3. $entry->title = $service->newTitle($newTitle);
  4.
  5. // Find <g:price> attribute and update the price
  6. $baseAttributes = $entry->getGbaseAttribute("price");
  7. if (is_object($baseAttributes[0])) {
  8.   $newPrice = "16.99 USD";
  9.   $baseAttributes[0]->text = $newPrice;
  10. }
  11.
  12. // Find <g:pages> attribute and update the number of pages
  13. $baseAttributes = $entry->getGbaseAttribute("pages");
  14. if (is_object($baseAttributes[0])) {
  15.   $newPages = "278";
  16.   $baseAttributes[0]->text = $newPages;
  17.
  18.   // Update the attribute type from "number" to "int"
  19.   if ($baseAttributes[0]->type == "number") {
  20.     $newType = "int";
  21.     $baseAttributes[0]->type = $newType;
  22.   }
  23. }
  24.
  25. // Remove <g:label> attributes
  26. $baseAttributes = $entry->getGbaseAttribute("label");
  27. foreach ($baseAttributes as $note) {
  28.   $entry->removeGbaseAttribute($note);
  29. }
  30.
  31. // Add new attributes
  32. $entry->addGbaseAttribute("note", "PHP 5", "text");
  33. $entry->addGbaseAttribute("note", "Web Programming", "text");
  34.
  35. // Save the changes by invoking save() on the entry object itself
  36. $dryRun = true;
  37. $entry->save($dryRun);
  38.
  39. // Or, save the changes by calling updateGbaseItem() on the service object
  40. // $dryRun = true;
  41. // $service->updateGbaseItem($entry, $dryRun);

After making the changes, either invoke save($dryRun) method on the Zend_Gdata_Gbase_ItemEntry object or call updateGbaseItem($entry, $dryRun) method on the Zend_Gdata_Gbase object to save the changes.

Delete an Item

You can remove an item by calling deleteGbaseItem() method:

  1. $dryRun = false;
  2. $service->deleteGbaseItem($entry, $dryRun);

Alternatively, you can invoke delete() on the Zend_Gdata_Gbase_ItemEntry object:

  1. $dryRun = false;
  2. $entry->delete($dryRun);
Using Google Apps Provisioning
Zend_Gdata
Zend Framework手册 中文版
Using Picasa Web Albums
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Gdata
  • Introduction
  • Authenticating with AuthSub
  • Using the Book Search Data API
  • Authenticating with ClientLogin
  • Using Google Calendar
  • Using Google Documents List Data API
  • Using Google Health
  • Using Google Spreadsheets
  • Using Google Apps Provisioning
  • Using Google Base
  • Using Picasa Web Albums
  • Using the YouTube Data API
  • Catching Gdata Exceptions


Using Picasa Web Albums - Zend Framework Manual

Using Google Base
Zend_Gdata
Zend Framework手册 中文版
Using the YouTube Data API

Using Picasa Web Albums

Picasa Web Albums is a service which allows users to maintain albums of their own pictures, and browse the albums and pictures of others. The API offers a programmatic interface to this service, allowing users to add to, update, and remove from their albums, as well as providing the ability to tag and comment on photos.

Access to public albums and photos is not restricted by account, however, a user must be logged in for non-read-only access.

For more information on the API, including instructions for enabling API access, refer to the » Picasa Web Albums Data API Overview.

Note: Authentication
 The API provides authentication via AuthSub (recommended) and ClientAuth. HTTP connections must be authenticated for write support, but non-authenticated connections have read-only access.

Connecting To The Service

The Picasa Web Albums API, like all GData APIs, is based off of the Atom Publishing Protocol (APP), an XML based format for managing web-based resources. Traffic between a client and the servers occurs over HTTP and allows for both authenticated and unauthenticated connections.

Before any transactions can occur, this connection needs to be made. Creating a connection to the Picasa servers involves two steps: creating an HTTP client and binding a Zend_Gdata_Photos service instance to that client.

Authentication

The Google Picasa API allows access to both public and private photo feeds. Public feeds do not require authentication, but are read-only and offer reduced functionality. Private feeds offers the most complete functionality but requires an authenticated connection to the Picasa servers. There are three authentication schemes that are supported by Google Picasa :

  • ClientAuth provides direct username/password authentication to the Picasa servers. Since this scheme requires that users provide your application with their password, this authentication is only recommended when other authentication schemes are insufficient.

  • AuthSub allows authentication to the Picasa servers via a Google proxy server. This provides the same level of convenience as ClientAuth but without the security risk, making this an ideal choice for web-based applications.

The Zend_Gdata library provides support for both authentication schemes. The rest of this chapter will assume that you are familiar the authentication schemes available and how to create an appropriate authenticated connection. For more information, please see section the Authentication section of this manual or the » Authentication Overview in the Google Data API Developer's Guide.

Creating A Service Instance

In order to interact with the servers, this library provides the Zend_Gdata_Photos service class. This class provides a common interface to the Google Data and Atom Publishing Protocol models and assists in marshaling requests to and from the servers.

Once deciding on an authentication scheme, the next step is to create an instance of Zend_Gdata_Photos. The class constructor takes an instance of Zend_Http_Client as a single argument. This provides an interface for AuthSub and ClientAuth authentication, as both of these require creation of a special authenticated HTTP client. If no arguments are provided, an unauthenticated instance of Zend_Http_Client will be automatically created.

The example below shows how to create a service class using ClientAuth authentication:

  1. // Parameters for ClientAuth authentication
  2. $service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
  3. $user = "sample.user@gmail.com";
  4. $pass = "pa$$w0rd";
  5.
  6. // Create an authenticated HTTP client
  7. $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
  8.
  9. // Create an instance of the service
  10. $service = new Zend_Gdata_Photos($client);

A service instance using AuthSub can be created in a similar, though slightly more lengthy fashion:

  1. session_start();
  2.
  3. /**
  4. * Returns the full URL of the current page, based upon env variables
  5. *
  6. * Env variables used:
  7. * $_SERVER['HTTPS'] = (on|off|)
  8. * $_SERVER['HTTP_HOST'] = value of the Host: header
  9. * $_SERVER['SERVER_PORT'] = port number (only used if not http/80,https/443)
  10. * $_SERVER['REQUEST_URI'] = the URI after the method of the HTTP request
  11. *
  12. * @return string Current URL
  13. */
  14. function getCurrentUrl()
  15. {
  16.     global $_SERVER;
  17.
  18.     /**
  19.      * Filter php_self to avoid a security vulnerability.
  20.      */
  21.     $php_request_uri = htmlentities(substr($_SERVER['REQUEST_URI'], 0,
  22.     strcspn($_SERVER['REQUEST_URI'], "\n\r")), ENT_QUOTES);
  23.
  24.     if (isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on') {
  25.         $protocol = 'https://';
  26.     } else {
  27.         $protocol = 'http://';
  28.     }
  29.     $host = $_SERVER['HTTP_HOST'];
  30.     if ($_SERVER['SERVER_PORT'] != '' &&
  31.         (($protocol == 'http://' && $_SERVER['SERVER_PORT'] != '80') ||
  32.         ($protocol == 'https://' && $_SERVER['SERVER_PORT'] != '443'))) {
  33.             $port = ':' . $_SERVER['SERVER_PORT'];
  34.     } else {
  35.         $port = '';
  36.     }
  37.     return $protocol . $host . $port . $php_request_uri;
  38. }
  39.
  40. /**
  41. * Returns the AuthSub URL which the user must visit to authenticate requests
  42. * from this application.
  43. *
  44. * Uses getCurrentUrl() to get the next URL which the user will be redirected
  45. * to after successfully authenticating with the Google service.
  46. *
  47. * @return string AuthSub URL
  48. */
  49. function getAuthSubUrl()
  50. {
  51.     $next = getCurrentUrl();
  52.     $scope = 'http://picasaweb.google.com/data';
  53.     $secure = false;
  54.     $session = true;
  55.     return Zend_Gdata_AuthSub::getAuthSubTokenUri($next, $scope, $secure,
  56.         $session);
  57. }
  58.
  59. /**
  60. * Returns a HTTP client object with the appropriate headers for communicating
  61. * with Google using AuthSub authentication.
  62. *
  63. * Uses the $_SESSION['sessionToken'] to store the AuthSub session token after
  64. * it is obtained. The single use token supplied in the URL when redirected
  65. * after the user succesfully authenticated to Google is retrieved from the
  66. * $_GET['token'] variable.
  67. *
  68. * @return Zend_Http_Client
  69. */
  70. function getAuthSubHttpClient()
  71. {
  72.     global $_SESSION, $_GET;
  73.     if (!isset($_SESSION['sessionToken']) && isset($_GET['token'])) {
  74.         $_SESSION['sessionToken'] =
  75.             Zend_Gdata_AuthSub::getAuthSubSessionToken($_GET['token']);
  76.     }
  77.     $client = Zend_Gdata_AuthSub::getHttpClient($_SESSION['sessionToken']);
  78.     return $client;
  79. }
  80.
  81. /**
  82. * Create a new instance of the service, redirecting the user
  83. * to the AuthSub server if necessary.
  84. */
  85. $service = new Zend_Gdata_Photos(getAuthSubHttpClient());

Finally, an unauthenticated server can be created for use with public feeds:

  1. // Create an instance of the service using an unauthenticated HTTP client
  2. $service = new Zend_Gdata_Photos();

Understanding and Constructing Queries

The primary method to request data from the service is by constructing a query. There are query classes for each of the following types:

  • User is used to specify the user whose data is being searched for, and is specified as a username. If no user is provided, "default" will be used instead to indicate the currently authenticated user (if authenticated).

  • Album is used to specify the album which is being searched for, and is specified as either an id, or an album name.

  • Photo is used to specify the photo which is being searched for, and is specified as an id.

A new UserQuery can be constructed as followed:

  1. $service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
  2. $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
  3. $service = new Zend_Gdata_Photos($client);
  4.
  5. $query = new Zend_Gdata_Photos_UserQuery();
  6. $query->setUser("sample.user");

For each query, a number of parameters limiting the search can be requested, or specified, with get(Parameter) and set(Parameter), respectively. They are as follows:

  • Projection sets the format of the data returned in the feed, as either "api" or "base". Normally, "api" is desired. The default is "api".

  • Type sets the type of element to be returned, as either "feed" or "entry". The default is "feed".

  • Access sets the visibility of items to be returned, as "all", "public", or "private". The default is "all". Non-public elements will only be returned if the query is searching for the authenticated user.

  • Tag sets a tag filter for returned items. When a tag is set, only items tagged with this value will return.

  • Kind sets the kind of elements to return. When kind is specified, only entries that match this value will be returned.

  • ImgMax sets the maximum image size for entries returned. Only image entries smaller than this value will be returned.

  • Thumbsize sets the thumbsize of entries that are returned. Any retrieved entry will have a thumbsize equal to this value.

  • User sets the user whose data is being searched for. The default is "default".

  • AlbumId sets the id of the album being searched for. This element only applies to album and photo queries. In the case of photo queries, this specifies the album that contains the requested photo. The album id is mutually exclusive with the album's name. Setting one unsets the other.

  • AlbumName sets the name of the album being searched for. This element only applies to the album and photo queries. In the case of photo queries, this specifies the album that contains the requested photo. The album name is mutually exclusive with the album's id. Setting one unsets the other.

  • PhotoId sets the id of the photo being searched for. This element only applies to photo queries.

Retrieving Feeds And Entries

The service has functions to retrieve a feed, or individual entries, for users, albums, and individual photos.

Retrieving A User

The service supports retrieving a user feed and list of the user's content. If the requested user is also the authenticated user, entries marked as "hidden" will also be returned.

The user feed can be accessed by passing the username to the getUserFeed method:

  1. $service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
  2. $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
  3. $service = new Zend_Gdata_Photos($client);
  4.
  5. try {
  6.     $userFeed = $service->getUserFeed("sample.user");
  7. } catch (Zend_Gdata_App_Exception $e) {
  8.     echo "Error: " . $e->getMessage();
  9. }

Or, the feed can be accessed by constructing a query, first:

  1. $service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
  2. $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
  3. $service = new Zend_Gdata_Photos($client);
  4.
  5. $query = new Zend_Gdata_Photos_UserQuery();
  6. $query->setUser("sample.user");
  7.
  8. try {
  9.     $userFeed = $service->getUserFeed(null, $query);
  10. } catch (Zend_Gdata_App_Exception $e) {
  11.     echo "Error: " . $e->getMessage();
  12. }

Constructing a query also provides the ability to request a user entry object:

  1. $service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
  2. $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
  3. $service = new Zend_Gdata_Photos($client);
  4.
  5. $query = new Zend_Gdata_Photos_UserQuery();
  6. $query->setUser("sample.user");
  7. $query->setType("entry");
  8.
  9. try {
  10.     $userEntry = $service->getUserEntry($query);
  11. } catch (Zend_Gdata_App_Exception $e) {
  12.     echo "Error: " . $e->getMessage();
  13. }

Retrieving An Album

The service supports retrieving an album feed and a list of the album's content.

The album feed is accessed by constructing a query object and passing it to getAlbumFeed:

  1. $service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
  2. $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
  3. $service = new Zend_Gdata_Photos($client);
  4.
  5. $query = new Zend_Gdata_Photos_AlbumQuery();
  6. $query->setUser("sample.user");
  7. $query->setAlbumId("1");
  8.
  9. try {
  10.     $albumFeed = $service->getAlbumFeed($query);
  11. } catch (Zend_Gdata_App_Exception $e) {
  12.     echo "Error: " . $e->getMessage();
  13. }

Alternatively, the query object can be given an album name with setAlbumName. Setting the album name is mutually exclusive with setting the album id, and setting one will unset the other.

Constructing a query also provides the ability to request an album entry object:

  1. $service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
  2. $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
  3. $service = new Zend_Gdata_Photos($client);
  4.
  5. $query = new Zend_Gdata_Photos_AlbumQuery();
  6. $query->setUser("sample.user");
  7. $query->setAlbumId("1");
  8. $query->setType("entry");
  9.
  10. try {
  11.     $albumEntry = $service->getAlbumEntry($query);
  12. } catch (Zend_Gdata_App_Exception $e) {
  13.     echo "Error: " . $e->getMessage();
  14. }

Retrieving A Photo

The service supports retrieving a photo feed and a list of associated comments and tags.

The photo feed is accessed by constructing a query object and passing it to getPhotoFeed:

  1. $service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
  2. $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
  3. $service = new Zend_Gdata_Photos($client);
  4.
  5. $query = new Zend_Gdata_Photos_PhotoQuery();
  6. $query->setUser("sample.user");
  7. $query->setAlbumId("1");
  8. $query->setPhotoId("100");
  9.
  10. try {
  11.     $photoFeed = $service->getPhotoFeed($query);
  12. } catch (Zend_Gdata_App_Exception $e) {
  13.     echo "Error: " . $e->getMessage();
  14. }

Constructing a query also provides the ability to request a photo entry object:

  1. $service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
  2. $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
  3. $service = new Zend_Gdata_Photos($client);
  4.
  5. $query = new Zend_Gdata_Photos_PhotoQuery();
  6. $query->setUser("sample.user");
  7. $query->setAlbumId("1");
  8. $query->setPhotoId("100");
  9. $query->setType("entry");
  10.
  11. try {
  12.     $photoEntry = $service->getPhotoEntry($query);
  13. } catch (Zend_Gdata_App_Exception $e) {
  14.     echo "Error: " . $e->getMessage();
  15. }

Retrieving A Comment

The service supports retrieving comments from a feed of a different type. By setting a query to return a kind of "comment", a feed request can return comments associated with a specific user, album, or photo.

Performing an action on each of the comments on a given photo can be accomplished as follows:

  1. $service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
  2. $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
  3. $service = new Zend_Gdata_Photos($client);
  4.
  5. $query = new Zend_Gdata_Photos_PhotoQuery();
  6. $query->setUser("sample.user");
  7. $query->setAlbumId("1");
  8. $query->setPhotoId("100");
  9. $query->setKind("comment");
  10.
  11. try {
  12.     $photoFeed = $service->getPhotoFeed($query);
  13.
  14.     foreach ($photoFeed as $entry) {
  15.         if ($entry instanceof Zend_Gdata_Photos_CommentEntry) {
  16.             // Do something with the comment
  17.         }
  18.     }
  19. } catch (Zend_Gdata_App_Exception $e) {
  20.     echo "Error: " . $e->getMessage();
  21. }

Retrieving A Tag

The service supports retrieving tags from a feed of a different type. By setting a query to return a kind of "tag", a feed request can return tags associated with a specific photo.

Performing an action on each of the tags on a given photo can be accomplished as follows:

  1. $service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
  2. $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
  3. $service = new Zend_Gdata_Photos($client);
  4.
  5. $query = new Zend_Gdata_Photos_PhotoQuery();
  6. $query->setUser("sample.user");
  7. $query->setAlbumId("1");
  8. $query->setPhotoId("100");
  9. $query->setKind("tag");
  10.
  11. try {
  12.     $photoFeed = $service->getPhotoFeed($query);
  13.
  14.     foreach ($photoFeed as $entry) {
  15.         if ($entry instanceof Zend_Gdata_Photos_TagEntry) {
  16.             // Do something with the tag
  17.         }
  18.     }
  19. } catch (Zend_Gdata_App_Exception $e) {
  20.     echo "Error: " . $e->getMessage();
  21. }

Creating Entries

The service has functions to create albums, photos, comments, and tags.

Creating An Album

The service supports creating a new album for an authenticated user:

  1. $service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
  2. $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
  3. $service = new Zend_Gdata_Photos($client);
  4.
  5. $entry = new Zend_Gdata_Photos_AlbumEntry();
  6. $entry->setTitle($service->newTitle("test album"));
  7.
  8. $service->insertAlbumEntry($entry);

Creating A Photo

The service supports creating a new photo for an authenticated user:

  1. $service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
  2. $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
  3. $service = new Zend_Gdata_Photos($client);
  4.
  5. // $photo is the name of a file uploaded via an HTML form
  6.
  7. $fd = $service->newMediaFileSource($photo["tmp_name"]);
  8. $fd->setContentType($photo["type"]);
  9.
  10. $entry = new Zend_Gdata_Photos_PhotoEntry();
  11. $entry->setMediaSource($fd);
  12. $entry->setTitle($service->newTitle($photo["name"]));
  13.
  14. $albumQuery = new Zend_Gdata_Photos_AlbumQuery;
  15. $albumQuery->setUser("sample.user");
  16. $albumQuery->setAlbumId("1");
  17.
  18. $albumEntry = $service->getAlbumEntry($albumQuery);
  19.
  20. $service->insertPhotoEntry($entry, $albumEntry);

Creating A Comment

The service supports creating a new comment for a photo:

  1. $service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
  2. $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
  3. $service = new Zend_Gdata_Photos($client);
  4.
  5. $entry = new Zend_Gdata_Photos_CommentEntry();
  6. $entry->setTitle($service->newTitle("comment"));
  7. $entry->setContent($service->newContent("comment"));
  8.
  9. $photoQuery = new Zend_Gdata_Photos_PhotoQuery;
  10. $photoQuery->setUser("sample.user");
  11. $photoQuery->setAlbumId("1");
  12. $photoQuery->setPhotoId("100");
  13. $photoQuery->setType('entry');
  14.
  15. $photoEntry = $service->getPhotoEntry($photoQuery);
  16.
  17. $service->insertCommentEntry($entry, $photoEntry);

Creating A Tag

The service supports creating a new tag for a photo:

  1. $service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
  2. $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
  3. $service = new Zend_Gdata_Photos($client);
  4.
  5. $entry = new Zend_Gdata_Photos_TagEntry();
  6. $entry->setTitle($service->newTitle("tag"));
  7.
  8. $photoQuery = new Zend_Gdata_Photos_PhotoQuery;
  9. $photoQuery->setUser("sample.user");
  10. $photoQuery->setAlbumId("1");
  11. $photoQuery->setPhotoId("100");
  12. $photoQuery->setType('entry');
  13.
  14. $photoEntry = $service->getPhotoEntry($photoQuery);
  15.
  16. $service->insertTagEntry($entry, $photoEntry);

Deleting Entries

The service has functions to delete albums, photos, comments, and tags.

Deleting An Album

The service supports deleting an album for an authenticated user:

  1. $service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
  2. $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
  3. $service = new Zend_Gdata_Photos($client);
  4.
  5. $albumQuery = new Zend_Gdata_Photos_AlbumQuery;
  6. $albumQuery->setUser("sample.user");
  7. $albumQuery->setAlbumId("1");
  8. $albumQuery->setType('entry');
  9.
  10. $entry = $service->getAlbumEntry($albumQuery);
  11.
  12. $service->deleteAlbumEntry($entry, true);

Deleting A Photo

The service supports deleting a photo for an authenticated user:

  1. $service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
  2. $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
  3. $service = new Zend_Gdata_Photos($client);
  4.
  5. $photoQuery = new Zend_Gdata_Photos_PhotoQuery;
  6. $photoQuery->setUser("sample.user");
  7. $photoQuery->setAlbumId("1");
  8. $photoQuery->setPhotoId("100");
  9. $photoQuery->setType('entry');
  10.
  11. $entry = $service->getPhotoEntry($photoQuery);
  12.
  13. $service->deletePhotoEntry($entry, true);

Deleting A Comment

The service supports deleting a comment for an authenticated user:

  1. $service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
  2. $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
  3. $service = new Zend_Gdata_Photos($client);
  4.
  5. $photoQuery = new Zend_Gdata_Photos_PhotoQuery;
  6. $photoQuery->setUser("sample.user");
  7. $photoQuery->setAlbumId("1");
  8. $photoQuery->setPhotoId("100");
  9. $photoQuery->setType('entry');
  10.
  11. $path = $photoQuery->getQueryUrl() . '/commentid/' . "1000";
  12.
  13. $entry = $service->getCommentEntry($path);
  14.
  15. $service->deleteCommentEntry($entry, true);

Deleting A Tag

The service supports deleting a tag for an authenticated user:

  1. $service = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
  2. $client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
  3. $service = new Zend_Gdata_Photos($client);
  4.
  5. $photoQuery = new Zend_Gdata_Photos_PhotoQuery;
  6. $photoQuery->setUser("sample.user");
  7. $photoQuery->setAlbumId("1");
  8. $photoQuery->setPhotoId("100");
  9. $photoQuery->setKind("tag");
  10. $query = $photoQuery->getQueryUrl();
  11.
  12. $photoFeed = $service->getPhotoFeed($query);
  13.
  14. foreach ($photoFeed as $entry) {
  15.     if ($entry instanceof Zend_Gdata_Photos_TagEntry) {
  16.         if ($entry->getContent() == $tagContent) {
  17.             $tagEntry = $entry;
  18.         }
  19.     }
  20. }
  21.
  22. $service->deleteTagEntry($tagEntry, true);

Optimistic Concurrency (Notes On Deletion)

GData feeds, including those of the Picasa Web Albums service, implement optimistic concurrency, a versioning system that prevents users from overwriting changes, inadvertently. When deleting a entry through the service class, if the entry has been modified since it was last fetched, an exception will be thrown, unless explicitly set otherwise (in which case the deletion is retried on the updated entry).

An example of how to handle versioning during a deletion is shown by deleteAlbumEntry:

  1. // $album is the albumEntry to be deleted
  2. try {
  3.     $this->delete($album);
  4. } catch (Zend_Gdata_App_HttpException $e) {
  5.     if ($e->getMessage()->getStatus() === 409) {
  6.         $entry =
  7.             new Zend_Gdata_Photos_AlbumEntry($e->getMessage()->getBody());
  8.         $this->delete($entry->getLink('edit')->href);
  9.     } else {
  10.         throw $e;
  11.     }
  12. }
Using Google Base
Zend_Gdata
Zend Framework手册 中文版
Using the YouTube Data API
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Gdata
  • Introduction
  • Authenticating with AuthSub
  • Using the Book Search Data API
  • Authenticating with ClientLogin
  • Using Google Calendar
  • Using Google Documents List Data API
  • Using Google Health
  • Using Google Spreadsheets
  • Using Google Apps Provisioning
  • Using Google Base
  • Using Picasa Web Albums
  • Using the YouTube Data API
  • Catching Gdata Exceptions


Using the YouTube Data API - Zend Framework Manual

Using Picasa Web Albums
Zend_Gdata
Zend Framework手册 中文版
Catching Gdata Exceptions

Using the YouTube Data API

The YouTube Data API offers read and write access to YouTube's content. Users can perform unauthenticated requests to Google Data feeds to retrieve feeds of popular videos, comments, public information about YouTube user profiles, user playlists, favorites, subscriptions and so on.

For more information on the YouTube Data API, please refer to the official » PHP Developer's Guide on code.google.com.

Authentication

The YouTube Data API allows read-only access to public data, which does not require authentication. For any write requests, a user needs to authenticate either using ClientLogin or AuthSub authentication. Please refer to the » Authentication section in the PHP Developer's Guide for more detail.

Developer Keys and Client ID

A developer key identifies the YouTube developer that is submitting an API request. A client ID identifies your application for logging and debugging purposes. Please visit » http://code.google.com/apis/youtube/dashboard/ to obtain a developer key and client ID. The example below demonstrates how to pass the developer key and client ID to the » Zend_Gdata_YouTube service object.

Example #1 Passing a Developer Key and ClientID to Zend_Gdata_YouTube

  1. $yt = new Zend_Gdata_YouTube($httpClient,
  2.                              $applicationId,
  3.                              $clientId,
  4.                              $developerKey);

Retrieving public video feeds

The YouTube Data API provides numerous feeds that return a list of videos, such as standard feeds, related videos, video responses, user's uploads, and user's favorites. For example, the user's uploads feed returns all videos uploaded by a specific user. See the » YouTube API reference guide for a detailed list of available feeds.

Searching for videos by metadata

You can retrieve a list of videos that match specified search criteria, using the YouTubeQuery class. The following query looks for videos which contain the word "cat" in their metadata, starting with the 10th video and displaying 20 videos per page, ordered by the view count.

Example #2 Searching for videos

  1. $yt = new Zend_Gdata_YouTube();
  2. $query = $yt->newVideoQuery();
  3. $query->videoQuery = 'cat';
  4. $query->startIndex = 10;
  5. $query->maxResults = 20;
  6. $query->orderBy = 'viewCount';
  7.
  8. echo $query->queryUrl . "\n";
  9. $videoFeed = $yt->getVideoFeed($query);
  10.
  11. foreach ($videoFeed as $videoEntry) {
  12.     echo "---------VIDEO----------\n";
  13.     echo "Title: " . $videoEntry->getVideoTitle() . "\n";
  14.     echo "\nDescription:\n";
  15.     echo $videoEntry->getVideoDescription();
  16.     echo "\n\n\n";
  17. }

For more details on the different query parameters, please refer to the » Reference Guide. The available helper functions in » Zend_Gdata_YouTube_VideoQuery for each of these parameters are described in more detail in the » PHP Developer's Guide.

Searching for videos by categories and tags/keywords

Searching for videos in specific categories is done by generating a » specially formatted URL. For example, to search for comedy videos which contain the keyword dog:

Example #3 Searching for videos in specific categories

  1. $yt = new Zend_Gdata_YouTube();
  2. $query = $yt->newVideoQuery();
  3. $query->category = 'Comedy/dog';
  4.
  5. echo $query->queryUrl . "\n";
  6. $videoFeed = $yt->getVideoFeed($query);

Retrieving standard feeds

The YouTube Data API has a number of » standard feeds. These standard feeds can be retrieved as » Zend_Gdata_YouTube_VideoFeed objects using the specified URLs, using the predefined constants within the » Zend_Gdata_YouTube class (Zend_Gdata_YouTube::STANDARD_TOP_RATED_URI for example) or using the predefined helper methods (see code listing below).

To retrieve the top rated videos using the helper method:

Example #4 Retrieving a standard video feed

  1. $yt = new Zend_Gdata_YouTube();
  2. $videoFeed = $yt->getTopRatedVideoFeed();

There are also query parameters to specify the time period over which the standard feed is computed.

For example, to retrieve the top rated videos for today:

Example #5 Using a Zend_Gdata_YouTube_VideoQuery to Retrieve Videos

  1. $yt = new Zend_Gdata_YouTube();
  2. $query = $yt->newVideoQuery();
  3. $query->setTime('today');
  4. $videoFeed = $yt->getTopRatedVideoFeed($query);

Alternatively, you could just retrieve the feed using the URL:

Example #6 Retrieving a video feed by URL

  1. $yt = new Zend_Gdata_YouTube();
  2. $url = 'http://gdata.youtube.com/feeds/standardfeeds/top_rated?time=today'
  3. $videoFeed = $yt->getVideoFeed($url);

Retrieving videos uploaded by a user

You can retrieve a list of videos uploaded by a particular user using a simple helper method. This example retrieves videos uploaded by the user 'liz'.

Example #7 Retrieving videos uploaded by a specific user

  1. $yt = new Zend_Gdata_YouTube();
  2. $videoFeed = $yt->getUserUploads('liz');

Retrieving videos favorited by a user

You can retrieve a list of a user's favorite videos using a simple helper method. This example retrieves videos favorited by the user 'liz'.

Example #8 Retrieving a user's favorite videos

  1. $yt = new Zend_Gdata_YouTube();
  2. $videoFeed = $yt->getUserFavorites('liz');

Retrieving video responses for a video

You can retrieve a list of a video's video responses using a simple helper method. This example retrieves video response for a video with the ID 'abc123813abc'.

Example #9 Retrieving a feed of video responses

  1. $yt = new Zend_Gdata_YouTube();
  2. $videoFeed = $yt->getVideoResponseFeed('abc123813abc');

Retrieving video comments

The comments for each YouTube video can be retrieved in several ways. To retrieve the comments for the video with the ID 'abc123813abc', use the following code:

Example #10 Retrieving a feed of video comments from a video ID

  1. $yt = new Zend_Gdata_YouTube();
  2. $commentFeed = $yt->getVideoCommentFeed('abc123813abc');
  3.
  4. foreach ($commentFeed as $commentEntry) {
  5.     echo $commentEntry->title->text . "\n";
  6.     echo $commentEntry->content->text . "\n\n\n";
  7. }

Comments can also be retrieved for a video if you have a copy of the » Zend_Gdata_YouTube_VideoEntry object:

Example #11 Retrieving a Feed of Video Comments from a Zend_Gdata_YouTube_VideoEntry

  1. $yt = new Zend_Gdata_YouTube();
  2. $videoEntry = $yt->getVideoEntry('abc123813abc');
  3. // we don't know the video ID in this example, but we do have the URL
  4. $commentFeed = $yt->getVideoCommentFeed(null,
  5.                                         $videoEntry->comments->href);

Retrieving playlist feeds

The YouTube Data API provides information about users, including profiles, playlists, subscriptions, and more.

Retrieving the playlists of a user

The library provides a helper method to retrieve the playlists associated with a given user. To retrieve the playlists for the user 'liz':

Example #12 Retrieving the playlists of a user

  1. $yt = new Zend_Gdata_YouTube();
  2. $playlistListFeed = $yt->getPlaylistListFeed('liz');
  3.
  4. foreach ($playlistListFeed as $playlistEntry) {
  5.     echo $playlistEntry->title->text . "\n";
  6.     echo $playlistEntry->description->text . "\n";
  7.     echo $playlistEntry->getPlaylistVideoFeedUrl() . "\n\n\n";
  8. }

Retrieving a specific playlist

The library provides a helper method to retrieve the videos associated with a given playlist. To retrieve the playlists for a specific playlist entry:

Example #13 Retrieving a specific playlist

  1. $feedUrl = $playlistEntry->getPlaylistVideoFeedUrl();
  2. $playlistVideoFeed = $yt->getPlaylistVideoFeed($feedUrl);

Retrieving a list of a user's subscriptions

A user can have several types of subscriptions: channel subscription, tag subscription, or favorites subscription. A » Zend_Gdata_YouTube_SubscriptionEntry is used to represent individual subscriptions.

To retrieve all subscriptions for the user 'liz':

Example #14 Retrieving all subscriptions for a user

  1. $yt = new Zend_Gdata_YouTube();
  2. $subscriptionFeed = $yt->getSubscriptionFeed('liz');
  3.
  4. foreach ($subscriptionFeed as $subscriptionEntry) {
  5.     echo $subscriptionEntry->title->text . "\n";
  6. }

Retrieving a user's profile

You can retrieve the public profile information for any YouTube user. To retrieve the profile for the user 'liz':

Example #15 Retrieving a user's profile

  1. $yt = new Zend_Gdata_YouTube();
  2. $userProfile = $yt->getUserProfile('liz');
  3. echo "username: " . $userProfile->username->text . "\n";
  4. echo "age: " . $userProfile->age->text . "\n";
  5. echo "hometown: " . $userProfile->hometown->text . "\n";

Uploading Videos to YouTube

Please make sure to review the diagrams in the » protocol guide on code.google.com for a high-level overview of the upload process. Uploading videos can be done in one of two ways: either by uploading the video directly or by sending just the video meta-data and having a user upload the video through an HTML form.

In order to upload a video directly, you must first construct a new » Zend_Gdata_YouTube_VideoEntry object and specify some required meta-data The following example shows uploading the Quicktime video "mytestmovie.mov" to YouTube with the following properties:

Metadata used in the code-sample below
Property | Value
Title | My Test Movie
Category | Autos
Keywords | cars, funny
Description | My description
Filename | mytestmovie.mov
File MIME type | video/quicktime
Video private? | FALSE
Video location | 37, -122 (lat, long)
Developer Tags | mydevelopertag, anotherdevelopertag

The code below creates a blank » Zend_Gdata_YouTube_VideoEntry to be uploaded. A » Zend_Gdata_App_MediaFileSource object is then used to hold the actual video file. Under the hood, the » Zend_Gdata_YouTube_Extension_MediaGroup object is used to hold all of the video's meta-data. Our helper methods detailed below allow you to just set the video meta-data without having to worry about the media group object. The $uploadUrl is the location where the new entry gets posted to. This can be specified either with the $userName of the currently authenticated user, or, alternatively, you can simply use the string 'default' to refer to the currently authenticated user.

Example #16 Uploading a video

  1. $yt = new Zend_Gdata_YouTube($httpClient);
  2. $myVideoEntry = new Zend_Gdata_YouTube_VideoEntry();
  3.
  4. $filesource = $yt->newMediaFileSource('mytestmovie.mov');
  5. $filesource->setContentType('video/quicktime');
  6. $filesource->setSlug('mytestmovie.mov');
  7.
  8. $myVideoEntry->setMediaSource($filesource);
  9.
  10. $myVideoEntry->setVideoTitle('My Test Movie');
  11. $myVideoEntry->setVideoDescription('My Test Movie');
  12. // Note that category must be a valid YouTube category !
  13. $myVideoEntry->setVideoCategory('Comedy');
  14.
  15. // Set keywords, note that this must be a comma separated string
  16. // and that each keyword cannot contain whitespace
  17. $myVideoEntry->SetVideoTags('cars, funny');
  18.
  19. // Optionally set some developer tags
  20. $myVideoEntry->setVideoDeveloperTags(array('mydevelopertag',
  21.                                            'anotherdevelopertag'));
  22.
  23. // Optionally set the video's location
  24. $yt->registerPackage('Zend_Gdata_Geo');
  25. $yt->registerPackage('Zend_Gdata_Geo_Extension');
  26. $where = $yt->newGeoRssWhere();
  27. $position = $yt->newGmlPos('37.0 -122.0');
  28. $where->point = $yt->newGmlPoint($position);
  29. $myVideoEntry->setWhere($where);
  30.
  31. // Upload URI for the currently authenticated user
  32. $uploadUrl =
  33.     'http://uploads.gdata.youtube.com/feeds/users/default/uploads';
  34.
  35. // Try to upload the video, catching a Zend_Gdata_App_HttpException
  36. // if availableor just a regular Zend_Gdata_App_Exception
  37.
  38. try {
  39.     $newEntry = $yt->insertEntry($myVideoEntry,
  40.                                  $uploadUrl,
  41.                                  'Zend_Gdata_YouTube_VideoEntry');
  42. } catch (Zend_Gdata_App_HttpException $httpException) {
  43.     echo $httpException->getRawResponseBody();
  44. } catch (Zend_Gdata_App_Exception $e) {
  45.     echo $e->getMessage();
  46. }

To upload a video as private, simply use: $myVideoEntry->setVideoPrivate(); prior to performing the upload. $videoEntry->isVideoPrivate() can be used to check whether a video entry is private or not.

Browser-based upload

Browser-based uploading is performed almost identically to direct uploading, except that you do not attach a » Zend_Gdata_App_MediaFileSource object to the » Zend_Gdata_YouTube_VideoEntry you are constructing. Instead you simply submit all of your video's meta-data to receive back a token element which can be used to construct an HTML upload form.

Example #17 Browser-based upload

  1. $yt = new Zend_Gdata_YouTube($httpClient);
  2.
  3. $myVideoEntry= new Zend_Gdata_YouTube_VideoEntry();
  4. $myVideoEntry->setVideoTitle('My Test Movie');
  5. $myVideoEntry->setVideoDescription('My Test Movie');
  6.
  7. // Note that category must be a valid YouTube category
  8. $myVideoEntry->setVideoCategory('Comedy');
  9. $myVideoEntry->SetVideoTags('cars, funny');
  10.
  11. $tokenHandlerUrl = 'http://gdata.youtube.com/action/GetUploadToken';
  12. $tokenArray = $yt->getFormUploadToken($myVideoEntry, $tokenHandlerUrl);
  13. $tokenValue = $tokenArray['token'];
  14. $postUrl = $tokenArray['url'];

The above code prints out a link and a token that is used to construct an HTML form to display in the user's browser. A simple example form is shown below with $tokenValue representing the content of the returned token element, as shown being retrieved from $myVideoEntry above. In order for the user to be redirected to your website after submitting the form, make sure to append a $nextUrl parameter to the $postUrl above, which functions in the same way as the $next parameter of an AuthSub link. The only difference is that here, instead of a single-use token, a status and an id variable are returned in the URL.

Example #18 Browser-based upload: Creating the HTML form

  1. // place to redirect user after upload
  2. $nextUrl = 'http://mysite.com/youtube_uploads';
  3.
  4. $form = '<form action="'. $postUrl .'?nexturl='. $nextUrl .
  5.         '" method="post" enctype="multipart/form-data">'.
  6.         '<input name="file" type="file"/>'.
  7.         '<input name="token" type="hidden" value="'. $tokenValue .'"/>'.
  8.         '<input value="Upload Video File" type="submit" />'.
  9.         '</form>';

Checking upload status

After uploading a video, it will immediately be visible in an authenticated user's uploads feed. However, it will not be public on the site until it has been processed. Videos that have been rejected or failed to upload successfully will also only be in the authenticated user's uploads feed. The following code checks the status of a » Zend_Gdata_YouTube_VideoEntry to see if it is not live yet or if it has been rejected.

Example #19 Checking video upload status

  1. try {
  2.     $control = $videoEntry->getControl();
  3. } catch (Zend_Gdata_App_Exception $e) {
  4.     echo $e->getMessage();
  5. }
  6.
  7. if ($control instanceof Zend_Gdata_App_Extension_Control) {
  8.     if ($control->getDraft() != null &&
  9.         $control->getDraft()->getText() == 'yes') {
  10.         $state = $videoEntry->getVideoState();
  11.
  12.         if ($state instanceof Zend_Gdata_YouTube_Extension_State) {
  13.             print 'Upload status: '
  14.                   . $state->getName()
  15.                   .' '. $state->getText();
  16.         } else {
  17.             print 'Not able to retrieve the video status information'
  18.                   .' yet. ' . "Please try again shortly.\n";
  19.         }
  20.     }
  21. }

Other Functions

In addition to the functionality described above, the YouTube API contains many other functions that allow you to modify video meta-data, delete video entries and use the full range of community features on the site. Some of the community features that can be modified through the API include: ratings, comments, playlists, subscriptions, user profiles, contacts and messages.

Please refer to the full documentation available in the » PHP Developer's Guide on code.google.com.

Using Picasa Web Albums
Zend_Gdata
Zend Framework手册 中文版
Catching Gdata Exceptions
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Gdata
  • Introduction
  • Authenticating with AuthSub
  • Using the Book Search Data API
  • Authenticating with ClientLogin
  • Using Google Calendar
  • Using Google Documents List Data API
  • Using Google Health
  • Using Google Spreadsheets
  • Using Google Apps Provisioning
  • Using Google Base
  • Using Picasa Web Albums
  • Using the YouTube Data API
  • Catching Gdata Exceptions


Catching Gdata Exceptions - Zend Framework Manual

Using the YouTube Data API
Zend_Gdata
Zend Framework手册 中文版
Zend_Http

Catching Gdata Exceptions

The Zend_Gdata_App_Exception class is a base class for exceptions thrown by Zend_Gdata. You can catch any exception thrown by Zend_Gdata by catching Zend_Gdata_App_Exception.

  1. try {
  2.     $client =
  3.         Zend_Gdata_ClientLogin::getHttpClient($username, $password);
  4. } catch(Zend_Gdata_App_Exception $ex) {
  5.     // Report the exception to the user
  6.     die($ex->getMessage());
  7. }

The following exception subclasses are used by Zend_Gdata:

  • Zend_Gdata_App_AuthException indicates that the user's account credentials were not valid.

  • Zend_Gdata_App_BadMethodCallException indicates that a method was called for a service that does not support the method. For example, the CodeSearch service does not support post().

  • Zend_Gdata_App_HttpException indicates that an HTTP request was not successful. Provides the ability to get the full Zend_Http_Response object to determine the exact cause of the failure in cases where $e->getMessage() does not provide enough details.

  • Zend_Gdata_App_InvalidArgumentException is thrown when the application provides a value that is not valid in a given context. For example, specifying a Calendar visibility value of "banana", or fetching a Blogger feed without specifying any blog name.

  • Zend_Gdata_App_CaptchaRequiredException is thrown when a ClientLogin attempt receives a CAPTCHA challenge from the authentication service. This exception contains a token ID and a URL to a CAPTCHA challenge image. The image is a visual puzzle that should be displayed to the user. After collecting the user's response to the challenge image, the response can be included with the next ClientLogin attempt.The user can alternatively be directed to this website: https://www.google.com/accounts/DisplayUnlockCaptcha Further information can be found in the ClientLogin documentation.

You can use these exception subclasses to handle specific exceptions differently. See the API documentation for information on which exception subclasses are thrown by which methods in Zend_Gdata.

  1. try {
  2.     $client = Zend_Gdata_ClientLogin::getHttpClient($username,
  3.                                                     $password,
  4.                                                     $service);
  5. } catch(Zend_Gdata_App_AuthException $authEx) {
  6.     // The user's credentials were incorrect.
  7.     // It would be appropriate to give the user a second try.
  8.     ...
  9. } catch(Zend_Gdata_App_HttpException $httpEx) {
  10.     // Google Data servers cannot be contacted.
  11.     die($httpEx->getMessage);}
Using the YouTube Data API
Zend_Gdata
Zend Framework手册 中文版
Zend_Http
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Gdata
  • Introduction
  • Authenticating with AuthSub
  • Using the Book Search Data API
  • Authenticating with ClientLogin
  • Using Google Calendar
  • Using Google Documents List Data API
  • Using Google Health
  • Using Google Spreadsheets
  • Using Google Apps Provisioning
  • Using Google Base
  • Using Picasa Web Albums
  • Using the YouTube Data API
  • Catching Gdata Exceptions


Zend_Http - Zend Framework Manual

Catching Gdata Exceptions
Zend Framework Reference
Zend Framework手册 中文版
Zend_Http_Client - 介绍

Zend_Http

Table of Contents
  • Zend_Http_Client - 介绍
  • Zend_Http_Client - Advanced Usage
  • Zend_Http_Client - Connection Adapters
  • Zend_Http_Cookie and Zend_Http_CookieJar
  • Zend_Http_Response
Catching Gdata Exceptions
Zend Framework Reference
Zend Framework手册 中文版
Zend_Http_Client - 介绍
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


Zend_Http_Client - 介绍 - Zend Framework Manual

Zend_Http
Zend_Http
Zend Framework手册 中文版
Zend_Http_Client - Advanced Usage

Zend_Http_Client - 介绍

介绍

Zend_Http_Client 提供了一个简单的界面来执行HTTP请求。Zend_Http_Client 支持 作为一个 HTTP 客户端应有的大多数简单功能，也包括象HTTP认证和文件上传等更加 复杂的功能。成功的请求和大多数失败的请求将返回一个 Zend_Http_Response 对象， 该对象提供了对响应的头部信息和主体信息的访问。 （见Zend_Http_Response）

构造器类可选的第一个参数可以是一个URL（字符串或者 Zend_Uri_Http 对象）， 第二个可选参数是一个包含配置参数的数组。这两个参数也可以全空，之后由 setUri()和setConfig()方法提供。

Example #1 初始化一个 Zend_Http_Client 对象

$client = new Zend_Http_Client('http://example.org', array(
    'maxredirects' => 0,
    'timeout'      => 30));

// 上述代码和下面的代码是两种不同的写法
$client = new Zend_Http_Client();
$client->setUri('http://example.org');
$client->setConfig(array(
    'maxredirects' => 0,
    'timeout'      => 30));

配置参数

构造器和 setConfig() 方法接受一个复合的配置参数数组，因为这些配置参数 有一个缺省值，所以是否配置这些参数都是可选的。

Zend_Http_Client 配置参数
参数 | 描述 | 值的类型 | 缺省值
maxredirects | 随后的重定向的最大值 (0 = none) | 整数 | 5
strict | 是否执行头部名称的确认，当设置为 False 时，将忽略确认，通常情况下不应改变这个参数的值。 | 布尔值 | true
strictredirects | 重定向时是否严格遵守 RFC (见 HTTP Redirections) | 布尔值 | false
useragent | 用户代理的识别字符串（含在请求的头部信息内） | 字符串 | 'Zend_Http_Client'
timeout | 连接超时 (单位是秒) | 整数 | 10
httpversion | HTTP 协议版本 (通常是 '1.1' 或 '1.0') | 字符串 | '1.1'
adapter | 连接适配器类时使用（见 Zend_Http_Client - Connection Adapters） | 多种类型 | 'Zend_Http_Client_Adapter_Socket'
keepalive | 是否允许与服务器之间的 keep-alive 连接。如果在同一台服务器上 执行几个互相关联的请求时，keep-alive 连接是有用的而且有可能提高性能。 | 布尔值 | false
storeresponse | 是否保存上次的响应结果，以备今后使用getLastResponse()重新获取。如果设置为 false，getLastResponse() 将返回空。 | 布尔值 | true

执行基本 HTTP 请求

使用 request() 方法执行简单 HTTP 请求是件非常容易的事情，3行代码即可搞定：

Example #2 执行一个简单的 GET 请求

$client = new Zend_Http_Client('http://example.org');
$response = $client->request();
request() 带一个可选的参数 - 请求方法，它可以是 GET, POST, PUT, HEAD, DELETE, TRACE, OPTIONS 或 CONNECT 等由 HTTP 协议定义的方法。 [1] http://www.w3.org/Protocols/rfc2616/rfc2616.html . 为了方便起见，这些都被定义为类的常量：即 Zend_Http_Request::GET, Zend_Http_Request::POST 等等。

如果没有指定请求方法，则使用最后一次 setMethod() 设定的请求方法。 如果从未使用 setMethod()，那么缺省的请求方法是 GET（见上述的例子）。

Example #3 使用 GET 以外的请求方法

// 执行一个 POST 请求
$response = $client->request('POST');

// 另外一种执行 POST 请求的方式
$client->setMethod(Zend_Http_Client::POST);
$response = $client->request();

添加 GET 和 POST 参数

在一个HTTP请求中添加GET参数是非常简单的，既可以通过把参数指定为 URL的一部分，也可以通过使用 setParameterGet() 方法来添加。这个方 法把把GET参数的名称作为它的第一个参数，把GET参数的值作为它的第二 个参数。为了方便起见，setParameterGet() 方法也能接受单个复合数组 （名称 => 值）的 GET 参数，这种方式对于需要设置几个 GET 参数时更 加方便。

Example #4 设置 GET 参数

// 使用 setParameterGet 方法设置一个 GET 参数
$client->setParameterGet('knight', 'lancelot');

// 设置 URL 的等效方法
$client->setUri('http://example.com/index.php?knight=lancelot');

// 一次添加几个参数
$client->setParameterGet(array(
    'first_name'  => 'Bender',
    'middle_name' => 'Bending'
    'made_in'     => 'Mexico',
));

虽然 GET 参数可以和任何请求方法一起发送，但 POST 参数只能在 POST 请求内发送。给一个请求添加 POST 参数与添加 GET 参数非常类似，是由 setParameterPost() 方法完成的，该方法在结构上与 setParameterGet() 方法很相似。

Example #5 设置 POST 参数

// 设置一个 POST 参数
$client->setParameterPost('language', 'fr');

// 设置几个 POST 参数，其中的一个参数有几个值
$client->setParameterPost(array(
    'language'  => 'es',
    'country'   => 'ar',
    'selection' => array(45, 32, 80)
));
需要注意的是，当发送 POST 请求时，即可设置GET参数，也可设置POST参数。 另一方面，如果针对一个非 POST 请求设置 POST 参数，将不会被触发或给出 报错，因为它是没有用的。除非请求是一个 POST 请求，POST 参数都会被简 单地忽略掉。

访问最后一次的请求和响应

Zend_Http_Client 提供了访问客户端最后一次发送的请求和访问客户端最后 一次接收到的响应的方法。 Zend_Http_Client->getLastRequest() 不需要设置参数，同时 返回最后一次客户端发送的HTTP请求字符串。同样， Zend_Http_Client->getLastResponse() 返回客户端接收到的 最后一次Zend_Http_Response 对象。

[1] 见 RFC 2616 - .
Zend_Http
Zend_Http
Zend Framework手册 中文版
Zend_Http_Client - Advanced Usage
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Http
  • Zend_Http_Client - 介绍
  • Zend_Http_Client - Advanced Usage
  • Zend_Http_Client - Connection Adapters
  • Zend_Http_Cookie and Zend_Http_CookieJar
  • Zend_Http_Response


Zend_Http_Client - Connection Adapters - Zend Framework Manual

Zend_Http_Client - Advanced Usage
Zend_Http
Zend Framework手册 中文版
Zend_Http_Cookie and Zend_Http_CookieJar

Zend_Http_Client - Connection Adapters

Overview

Zend_Http_Client is based on a connection adapter design. The connection adapter is the object in charge of performing the actual connection to the server, as well as writing requests and reading responses. This connection adapter can be replaced, and you can create and extend the default connection adapters to suite your special needs, without the need to extend or replace the entire HTTP client class, and with the same interface.

Currently, the Zend_Http_Client class provides four built-in connection adapters:

  • Zend_Http_Client_Adapter_Socket (default)

  • Zend_Http_Client_Adapter_Proxy

  • Zend_Http_Client_Adapter_Curl

  • Zend_Http_Client_Adapter_Test

The Zend_Http_Client object's adapter connection adapter is set using the 'adapter' configuration option. When instantiating the client object, you can set the 'adapter' configuration option to a string containing the adapter's name (eg. 'Zend_Http_Client_Adapter_Socket') or to a variable holding an adapter object (eg. new Zend_Http_Client_Adapter_Test). You can also set the adapter later, using the Zend_Http_Client->setConfig() method.

The Socket Adapter

The default connection adapter is the Zend_Http_Client_Adapter_Socket adapter - this adapter will be used unless you explicitly set the connection adapter. The Socket adapter is based on PHP's built-in fsockopen() function, and does not require any special extensions or compilation flags.

The Socket adapter allows several extra configuration options that can be set using Zend_Http_Client->setConfig() or passed to the client constructor.

Zend_Http_Client_Adapter_Socket configuration parameters
Parameter | Description | Expected Type | Default Value
persistent | Whether to use persistent TCP connections | boolean | FALSE
ssltransport | SSL transport layer (eg. 'sslv2', 'tls') | string | ssl
sslcert | Path to a PEM encoded SSL certificate | string | NULL
sslpassphrase | Passphrase for the SSL certificate file | string | NULL

Note: Persistent TCP Connections
 Using persistent TCP connections can potentially speed up HTTP requests - but in most use cases, will have little positive effect and might overload the HTTP server you are connecting to.
It is recommended to use persistent TCP connections only if you connect to the same server very frequently, and are sure that the server is capable of handling a large number of concurrent connections. In any case you are encouraged to benchmark the effect of persistent connections on both the client speed and server load before using this option.
Additionally, when using persistent connections it is recommended to enable Keep-Alive HTTP requests as described in 配置参数 - otherwise persistent connections might have little or no effect.

Note: HTTPS SSL Stream Parameters
 ssltransport, sslcert and sslpassphrase are only relevant when connecting using HTTPS.
While the default SSL settings should work for most applications, you might need to change them if the server you are connecting to requires special client setup. If so, you should read the sections about SSL transport layers and options » here.

Example #1 Changing the HTTPS transport layer

  1. // Set the configuration parameters
  2. $config = array(
  3.     'adapter'      => 'Zend_Http_Client_Adapter_Socket',
  4.     'ssltransport' => 'tls'
  5. );
  6.
  7. // Instantiate a client object
  8. $client = new Zend_Http_Client('https://www.example.com', $config);
  9.
  10. // The following request will be sent over a TLS secure connection.
  11. $response = $client->request();

The result of the example above will be similar to opening a TCP connection using the following PHP command:

fsockopen('tls://www.example.com', 443)

Customizing and accessing the Socket adapter stream context

Starting from Zend Framework 1.9, Zend_Http_Client_Adapter_Socket provides direct access to the underlying » stream context used to connect to the remote server. This allows the user to pass specific options and parameters to the TCP stream, and to the SSL wrapper in case of HTTPS connections.

You can access the stream context using the following methods of Zend_Http_Client_Adapter_Socket:

  • setStreamContext($context) Sets the stream context to be used by the adapter. Can accept either a stream context resource created using the » stream_context_create() PHP function, or an array of stream context options, in the same format provided to this function. Providing an array will create a new stream context using these options, and set it.

  • getStreamContext() Get the stream context of the adapter. If no stream context was set, will create a default stream context and return it. You can then set or get the value of different context options using regular PHP stream context functions.

Example #2 Setting stream context options for the Socket adapter

  1. // Array of options
  2. $options = array(
  3.     'socket' => array(
  4.         // Bind local socket side to a specific interface
  5.         'bindto' => '10.1.2.3:50505'
  6.     ),
  7.     'ssl' => array(
  8.         // Verify server side certificate,
  9.         // do not accept invalid or self-signed SSL certificates
  10.         'verify_peer' => true,
  11.         'allow_self_signed' => false,
  12.
  13.         // Capture the peer's certificate
  14.         'capture_peer_cert' => true
  15.     )
  16. );
  17.
  18. // Create an adapter object and attach it to the HTTP client
  19. $adapter = new Zend_Http_Client_Adapter_Socket();
  20. $client = new Zend_Http_Client();
  21. $client->setAdapter($adapter);
  22.
  23. // Method 1: pass the options array to setStreamContext()
  24. $adapter->setStreamContext($options);
  25.
  26. // Method 2: create a stream context and pass it to setStreamContext()
  27. $context = stream_context_create($options);
  28. $adapter->setStreamContext($context);
  29.
  30. // Method 3: get the default stream context and set the options on it
  31. $context = $adapter->getStreamContext();
  32. stream_context_set_option($context, $options);
  33.
  34. // Now, preform the request
  35. $response = $client->request();
  36.
  37. // If everything went well, you can now access the context again
  38. $opts = stream_context_get_options($adapter->getStreamContext());
  39. echo $opts['ssl']['peer_certificate'];

Note: Note that you must set any stream context options before using the adapter to preform actual requests. If no context is set before preforming HTTP requests with the Socket adapter, a default stream context will be created. This context resource could be accessed after preforming any requests using the getStreamContext() method.

The Proxy Adapter

The Zend_Http_Client_Adapter_Proxy adapter is similar to the default Socket adapter - only the connection is made through an HTTP proxy server instead of a direct connection to the target server. This allows usage of Zend_Http_Client behind proxy servers - which is sometimes needed for security or performance reasons.

Using the Proxy adapter requires several additional configuration parameters to be set, in addition to the default 'adapter' option:

Zend_Http_Client configuration parameters
Parameter | Description | Expected Type | Example Value
proxy_host | Proxy server address | string | 'proxy.myhost.com' or '10.1.2.3'
proxy_port | Proxy server TCP port | integer | 8080 (default) or 81
proxy_user | Proxy user name, if required | string | 'shahar' or '' for none (default)
proxy_pass | Proxy password, if required | string | 'secret' or '' for none (default)
proxy_auth | Proxy HTTP authentication type | string | Zend_Http_Client::AUTH_BASIC (default)

proxy_host should always be set - if it is not set, the client will fall back to a direct connection using Zend_Http_Client_Adapter_Socket. proxy_port defaults to '8080' - if your proxy listens on a different port you must set this one as well.

proxy_user and proxy_pass are only required if your proxy server requires you to authenticate. Providing these will add a 'Proxy-Authentication' header to the request. If your proxy does not require authentication, you can leave these two options out.

proxy_auth sets the proxy authentication type, if your proxy server requires authentication. Possibly values are similar to the ones accepted by the Zend_Http_Client::setAuth() method. Currently, only basic authentication (Zend_Http_Client::AUTH_BASIC) is supported.

Example #3 Using Zend_Http_Client behind a proxy server

  1. // Set the configuration parameters
  2. $config = array(
  3.     'adapter'    => 'Zend_Http_Client_Adapter_Proxy',
  4.     'proxy_host' => 'proxy.int.zend.com',
  5.     'proxy_port' => 8000,
  6.     'proxy_user' => 'shahar.e',
  7.     'proxy_pass' => 'bananashaped'
  8. );
  9.
  10. // Instantiate a client object
  11. $client = new Zend_Http_Client('http://www.example.com', $config);
  12.
  13. // Continue working...

As mentioned, if proxy_host is not set or is set to a blank string, the connection will fall back to a regular direct connection. This allows you to easily write your application in a way that allows a proxy to be used optionally, according to a configuration parameter.

Note: Since the proxy adapter inherits from Zend_Http_Client_Adapter_Socket, you can use the stream context access method (see Customizing and accessing the Socket adapter stream context) to set stream context options on Proxy connections as demonstrated above.

The cURL Adapter

cURL is a standard HTTP client library that is distributed with many operating systems and can be used in PHP via the cURL extension. It offers functionality for many special cases which can occur for a HTTP client and make it a perfect choice for a HTTP adapter. It supports secure connections, proxy, all sorts of authentication mechanisms and shines in applications that move large files around between servers.

Example #4 Setting cURL options

  1. $config = array(
  2.     'adapter'   => 'Zend_Http_Client_Adapter_Curl',
  3.     'curloptions' => array(CURLOPT_FOLLOWLOCATION => true),
  4. );
  5. $client = new Zend_Http_Client($uri, $config);

By default the cURL adapter is configured to behave exactly like the Socket Adapter and it also accepts the same configuration parameters as the Socket and Proxy adapters. You can also change the cURL options by either specifying the 'curloptions' key in the constructor of the adapter or by calling setCurlOption($name, $value). The $name key corresponds to the CURL_* constants of the cURL extension. You can get access to the Curl handle by calling $adapter->getHandle();

Example #5 Transfering Files by Handle

You can use cURL to transfer very large files over HTTP by filehandle.

  1. $putFileSize   = filesize("filepath");
  2. $putFileHandle = fopen("filepath", "r");
  3.
  4. $adapter = new Zend_Http_Client_Adapter_Curl();
  5. $client = new Zend_Http_Client();
  6. $client->setAdapter($adapter);
  7. $adapter->setConfig(array(
  8.     'curloptions' => array(
  9.         CURLOPT_INFILE => $putFileHandle,
  10.         CURLOPT_INFILESIZE => $putFileSize
  11.     )
  12. ));
  13. $client->request("PUT");

The Test Adapter

Sometimes, it is very hard to test code that relies on HTTP connections. For example, testing an application that pulls an RSS feed from a remote server will require a network connection, which is not always available.

For this reason, the Zend_Http_Client_Adapter_Test adapter is provided. You can write your application to use Zend_Http_Client, and just for testing purposes, for example in your unit testing suite, you can replace the default adapter with a Test adapter (a mock object), allowing you to run tests without actually performing server connections.

The Zend_Http_Client_Adapter_Test adapter provides an additional method, setResponse() method. This method takes one parameter, which represents an HTTP response as either text or a Zend_Http_Response object. Once set, your Test adapter will always return this response, without even performing an actual HTTP request.

Example #6 Testing Against a Single HTTP Response Stub

  1. // Instantiate a new adapter and client
  2. $adapter = new Zend_Http_Client_Adapter_Test();
  3. $client = new Zend_Http_Client('http://www.example.com', array(
  4.     'adapter' => $adapter
  5. ));
  6.
  7. // Set the expected response
  8. $adapter->setResponse(
  9.     "HTTP/1.1 200 OK"        . "\r\n" .
  10.     "Content-type: text/xml" . "\r\n" .
  11.                                "\r\n" .
  12.     '<?xml version="1.0" encoding="UTF-8"?>' .
  13.     '<rss version="2.0" ' .
  14.     '     xmlns:content="http://purl.org/rss/1.0/modules/content/"' .
  15.     '     xmlns:wfw="http://wellformedweb.org/CommentAPI/"' .
  16.     '     xmlns:dc="http://purl.org/dc/elements/1.1/">' .
  17.     '  <channel>' .
  18.     '    <title>Premature Optimization</title>' .
  19.     // and so on...
  20.     '</rss>');
  21.
  22. $response = $client->request('GET');
  23. // .. continue parsing $response..

The above example shows how you can preset your HTTP client to return the response you need. Then, you can continue testing your own code, without being dependent on a network connection, the server's response, etc. In this case, the test would continue to check how the application parses the XML in the response body.

Sometimes, a single method call to an object can result in that object performing multiple HTTP transactions. In this case, it's not possible to use setResponse() alone because there's no opportunity to set the next response(s) your program might need before returning to the caller.

Example #7 Testing Against Multiple HTTP Response Stubs

  1. // Instantiate a new adapter and client
  2. $adapter = new Zend_Http_Client_Adapter_Test();
  3. $client = new Zend_Http_Client('http://www.example.com', array(
  4.     'adapter' => $adapter
  5. ));
  6.
  7. // Set the first expected response
  8. $adapter->setResponse(
  9.     "HTTP/1.1 302 Found"      . "\r\n" .
  10.     "Location: /"             . "\r\n" .
  11.     "Content-Type: text/html" . "\r\n" .
  12.                                 "\r\n" .
  13.     '<html>' .
  14.     '  <head><title>Moved</title></head>' .
  15.     '  <body><p>This page has moved.</p></body>' .
  16.     '</html>');
  17.
  18. // Set the next successive response
  19. $adapter->addResponse(
  20.     "HTTP/1.1 200 OK"         . "\r\n" .
  21.     "Content-Type: text/html" . "\r\n" .
  22.                                 "\r\n" .
  23.     '<html>' .
  24.     '  <head><title>My Pet Store Home Page</title></head>' .
  25.     '  <body><p>...</p></body>' .
  26.     '</html>');
  27.
  28. // inject the http client object ($client) into your object
  29. // being tested and then test your object's behavior below

The setResponse() method clears any responses in the Zend_Http_Client_Adapter_Test's buffer and sets the first response that will be returned. The addResponse() method will add successive responses.

The responses will be replayed in the order that they were added. If more requests are made than the number of responses stored, the responses will cycle again in order.

In the example above, the adapter is configured to test your object's behavior when it encounters a 302 redirect. Depending on your application, following a redirect may or may not be desired behavior. In our example, we expect that the redirect will be followed and we configure the test adapter to help us test this. The initial 302 response is set up with the setResponse() method and the 200 response to be returned next is added with the addResponse() method. After configuring the test adapter, inject the HTTP client containing the adapter into your object under test and test its behavior.

If you need the adapter to fail on demand you can use setNextRequestWillFail($flag). The method will cause the next call to connect() to throw an Zend_Http_Client_Adapter_Exception exception. This can be useful when your application caches content from an external site (in case the site goes down) and you want to test this feature.

Example #8 Forcing the adapter to fail

  1. // Instantiate a new adapter and client
  2. $adapter = new Zend_Http_Client_Adapter_Test();
  3. $client = new Zend_Http_Client('http://www.example.com', array(
  4.     'adapter' => $adapter
  5. ));
  6.
  7. // Force the next request to fail with an exception
  8. $adapter->nextRequestWillFail(true);
  9.
  10. try {
  11.     // This call will result in a Zend_Http_Client_Adapter_Exception
  12.     $client->request();
  13. } catch (Zend_Http_Client_Adapter_Exception $e) {
  14.     // ...
  15. }
  16.
  17. // Further requests will work as expected until
  18. // you call setNextRequestWillFail(true) again

Creating your own connection adapters

You can create your own connection adapters and use them. You could, for example, create a connection adapter that uses persistent sockets, or a connection adapter with caching abilities, and use them as needed in your application.

In order to do so, you must create your own adapter class that implements the Zend_Http_Client_Adapter_Interface interface. The following example shows the skeleton of a user-implemented adapter class. All the public functions defined in this example must be defined in your adapter as well:

Example #9 Creating your own connection adapter

  1. class MyApp_Http_Client_Adapter_BananaProtocol
  2.     implements Zend_Http_Client_Adapter_Interface
  3. {
  4.     /**
  5.      * Set the configuration array for the adapter
  6.      *
  7.      * @param array $config
  8.      */
  9.     public function setConfig($config = array())
  10.     {
  11.         // This rarely changes - you should usually copy the
  12.         // implementation in Zend_Http_Client_Adapter_Socket.
  13.     }
  14.
  15.     /**
  16.      * Connect to the remote server
  17.      *
  18.      * @param string  $host
  19.      * @param int     $port
  20.      * @param boolean $secure
  21.      */
  22.     public function connect($host, $port = 80, $secure = false)
  23.     {
  24.         // Set up the connection to the remote server
  25.     }
  26.
  27.     /**
  28.      * Send request to the remote server
  29.      *
  30.      * @param string        $method
  31.      * @param Zend_Uri_Http $url
  32.      * @param string        $http_ver
  33.      * @param array         $headers
  34.      * @param string        $body
  35.      * @return string Request as text
  36.      */
  37.     public function write($method,
  38.                           $url,
  39.                           $http_ver = '1.1',
  40.                           $headers = array(),
  41.                           $body = '')
  42.     {
  43.         // Send request to the remote server.
  44.         // This function is expected to return the full request
  45.         // (headers and body) as a string
  46.     }
  47.
  48.     /**
  49.      * Read response from server
  50.      *
  51.      * @return string
  52.      */
  53.     public function read()
  54.     {
  55.         // Read response from remote server and return it as a string
  56.     }
  57.
  58.     /**
  59.      * Close the connection to the server
  60.      *
  61.      */
  62.     public function close()
  63.     {
  64.         // Close the connection to the remote server - called last.
  65.     }
  66. }
  67.
  68. // Then, you could use this adapter:
  69. $client = new Zend_Http_Client(array(
  70.     'adapter' => 'MyApp_Http_Client_Adapter_BananaProtocol'
  71. ));
Zend_Http_Client - Advanced Usage
Zend_Http
Zend Framework手册 中文版
Zend_Http_Cookie and Zend_Http_CookieJar
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Http
  • Zend_Http_Client - 介绍
  • Zend_Http_Client - Advanced Usage
  • Zend_Http_Client - Connection Adapters
  • Zend_Http_Cookie and Zend_Http_CookieJar
  • Zend_Http_Response


Zend_Http_Client - Advanced Usage - Zend Framework Manual

Zend_Http_Client - 介绍
Zend_Http
Zend Framework手册 中文版
Zend_Http_Client - Connection Adapters

Zend_Http_Client - Advanced Usage

HTTP Redirections

By default, Zend_Http_Client automatically handles HTTP redirections, and will follow up to 5 redirections. This can be changed by setting the 'maxredirects' configuration parameter.

According to the HTTP/1.1 RFC, HTTP 301 and 302 responses should be treated by the client by resending the same request to the specified location - using the same request method. However, most clients to not implement this and always use a GET request when redirecting. By default, Zend_Http_Client does the same - when redirecting on a 301 or 302 response, all GET and POST parameters are reset, and a GET request is sent to the new location. This behavior can be changed by setting the 'strictredirects' configuration parameter to boolean TRUE:

Example #1 Forcing RFC 2616 Strict Redirections on 301 and 302 Responses

  1. // Strict Redirections
  2. $client->setConfig(array('strictredirects' => true));
  3.
  4. // Non-strict Redirections
  5. $client->setConfig(array('strictredirects' => false));

You can always get the number of redirections done after sending a request using the getRedirectionsCount() method.

Adding Cookies and Using Cookie Persistence

Zend_Http_Client provides an easy interface for adding cookies to your request, so that no direct header modification is required. This is done using the setCookie() method. This method can be used in several ways:

Example #2 Setting Cookies Using setCookie()

  1. // Easy and simple: by providing a cookie name and cookie value
  2. $client->setCookie('flavor', 'chocolate chips');
  3.
  4. // By directly providing a raw cookie string (name=value)
  5. // Note that the value must be already URL encoded
  6. $client->setCookie('flavor=chocolate%20chips');
  7.
  8. // By providing a Zend_Http_Cookie object
  9. $cookie = Zend_Http_Cookie::fromString('flavor=chocolate%20chips');
  10. $client->setCookie($cookie);
For more information about Zend_Http_Cookie objects, see Zend_Http_Cookie and Zend_Http_CookieJar.

Zend_Http_Client also provides the means for cookie stickiness - that is having the client internally store all sent and received cookies, and resend them automatically on subsequent requests. This is useful, for example when you need to log in to a remote site first and receive and authentication or session ID cookie before sending further requests.

Example #3 Enabling Cookie Stickiness

  1. // To turn cookie stickiness on, set a Cookie Jar
  2. $client->setCookieJar();
  3.
  4. // First request: log in and start a session
  5. $client->setUri('http://example.com/login.php');
  6. $client->setParameterPost('user', 'h4x0r');
  7. $client->setParameterPost('password', '1337');
  8. $client->request('POST');
  9.
  10. // The Cookie Jar automatically stores the cookies set
  11. // in the response, like a session ID cookie.
  12.
  13. // Now we can send our next request - the stored cookies
  14. // will be automatically sent.
  15. $client->setUri('http://example.com/read_member_news.php');
  16. $client->request('GET');
For more information about the Zend_Http_CookieJar class, see The Zend_Http_CookieJar Class: Instantiation.

Setting Custom Request Headers

Setting custom headers can be done by using the setHeaders() method. This method is quite diverse and can be used in several ways, as the following example shows:

Example #4 Setting A Single Custom Request Header

  1. // Setting a single header, overwriting any previous value
  2. $client->setHeaders('Host', 'www.example.com');
  3.
  4. // Another way of doing the exact same thing
  5. $client->setHeaders('Host: www.example.com');
  6.
  7. // Setting several values for the same header
  8. // (useful mostly for Cookie headers):
  9. $client->setHeaders('Cookie', array(
  10.     'PHPSESSID=1234567890abcdef1234567890abcdef',
  11.     'language=he'
  12. ));

setHeader() can also be easily used to set multiple headers in one call, by providing an array of headers as a single parameter:

Example #5 Setting Multiple Custom Request Headers

  1. // Setting multiple headers, overwriting any previous value
  2. $client->setHeaders(array(
  3.     'Host' => 'www.example.com',
  4.     'Accept-encoding' => 'gzip,deflate',
  5.     'X-Powered-By' => 'Zend Framework'));
  6.
  7. // The array can also contain full array strings:
  8. $client->setHeaders(array(
  9.     'Host: www.example.com',
  10.     'Accept-encoding: gzip,deflate',
  11.     'X-Powered-By: Zend Framework'));

File Uploads

You can upload files through HTTP using the setFileUpload method. This method takes a file name as the first parameter, a form name as the second parameter, and data as a third optional parameter. If the third data parameter is NULL, the first file name parameter is considered to be a real file on disk, and Zend_Http_Client will try to read this file and upload it. If the data parameter is not NULL, the first file name parameter will be sent as the file name, but no actual file needs to exist on the disk. The second form name parameter is always required, and is equivalent to the "name" attribute of an >input< tag, if the file was to be uploaded through an HTML form. A fourth optional parameter provides the file's content-type. If not specified, and Zend_Http_Client reads the file from the disk, the mime_content_type function will be used to guess the file's content type, if it is available. In any case, the default MIME type will be application/octet-stream.

Example #6 Using setFileUpload to Upload Files

  1. // Uploading arbitrary data as a file
  2. $text = 'this is some plain text';
  3. $client->setFileUpload('some_text.txt', 'upload', $text, 'text/plain');
  4.
  5. // Uploading an existing file
  6. $client->setFileUpload('/tmp/Backup.tar.gz', 'bufile');
  7.
  8. // Send the files
  9. $client->request('POST');
In the first example, the $text variable is uploaded and will be available as $_FILES['upload'] on the server side. In the second example, the existing file /tmp/Backup.tar.gz is uploaded to the server and will be available as $_FILES['bufile']. The content type will be guesses automatically if possible - and if not, the content type will be set to 'application/octet-stream'.

Note: Uploading files
 When uploading files, the HTTP request content-type is automatically set to multipart/form-data. Keep in mind that you must send a POST or PUT request in order to upload files. Most servers will ignore the requests body on other request methods.

Sending Raw POST Data

You can use a Zend_Http_Client to send raw POST data using the setRawData() method. This method takes two parameters: the first is the data to send in the request body. The second optional parameter is the content-type of the data. While this parameter is optional, you should usually set it before sending the request - either using setRawData(), or with another method: setEncType().

Example #7 Sending Raw POST Data

  1. $xml = '<book>' .
  2.        '  <title>Islands in the Stream</title>' .
  3.        '  <author>Ernest Hemingway</author>' .
  4.        '  <year>1970</year>' .
  5.        '</book>';
  6.
  7. $client->setRawData($xml, 'text/xml')->request('POST');
  8.
  9. // Another way to do the same thing:
  10. $client->setRawData($xml)->setEncType('text/xml')->request('POST');
The data should be available on the server side through PHP's $HTTP_RAW_POST_DATA variable or through the php://input stream.

Note: Using raw POST data
 Setting raw POST data for a request will override any POST parameters or file uploads. You should not try to use both on the same request. Keep in mind that most servers will ignore the request body unless you send a POST request.

HTTP Authentication

Currently, Zend_Http_Client only supports basic HTTP authentication. This feature is utilized using the setAuth() method, or by specifying a username and a password in the URI. The setAuth() method takes 3 parameters: The user name, the password and an optional authentication type parameter. As mentioned, currently only basic authentication is supported (digest authentication support is planned).

Example #8 Setting HTTP Authentication User and Password

  1. // Using basic authentication
  2. $client->setAuth('shahar', 'myPassword!', Zend_Http_Client::AUTH_BASIC);
  3.
  4. // Since basic auth is default, you can just do this:
  5. $client->setAuth('shahar', 'myPassword!');
  6.
  7. // You can also specify username and password in the URI
  8. $client->setUri('http://christer:secret@example.com');

Sending Multiple Requests With the Same Client

Zend_Http_Client was also designed specifically to handle several consecutive requests with the same object. This is useful in cases where a script requires data to be fetched from several places, or when accessing a specific HTTP resource requires logging in and obtaining a session cookie, for example.

When performing several requests to the same host, it is highly recommended to enable the 'keepalive' configuration flag. This way, if the server supports keep-alive connections, the connection to the server will only be closed once all requests are done and the Client object is destroyed. This prevents the overhead of opening and closing TCP connections to the server.

When you perform several requests with the same client, but want to make sure all the request-specific parameters are cleared, you should use the resetParameters() method. This ensures that GET and POST parameters, request body and request-specific headers are reset and are not reused in the next request.

Note: Resetting parameters
 Note that non-request specific headers are not reset by default when the resetParameters() method is used. Only the 'Content-length' and 'Content-type' headers are reset. This allows you to set-and-forget headers like 'Accept-language' and 'Accept-encoding'
To clean all headers and other data except for URI and method, use resetParameters(true).

Another feature designed specifically for consecutive requests is the Cookie Jar object. Cookie Jars allow you to automatically save cookies set by the server in the first request, and send them on consecutive requests transparently. This allows, for example, going through an authentication request before sending the actual data fetching request.

If your application requires one authentication request per user, and consecutive requests might be performed in more than one script in your application, it might be a good idea to store the Cookie Jar object in the user's session. This way, you will only need to authenticate the user once every session.

Example #9 Performing consecutive requests with one client

  1. // First, instantiate the client
  2. $client = new Zend_Http_Client('http://www.example.com/fetchdata.php', array(
  3.     'keepalive' => true
  4. ));
  5.
  6. // Do we have the cookies stored in our session?
  7. if (isset($_SESSION['cookiejar']) &&
  8.     $_SESSION['cookiejar'] instanceof Zend_Http_CookieJar)) {
  9.
  10.     $client->setCookieJar($_SESSION['cookiejar']);
  11. } else {
  12.     // If we don't, authenticate and store cookies
  13.     $client->setCookieJar();
  14.     $client->setUri('http://www.example.com/login.php');
  15.     $client->setParameterPost(array(
  16.         'user' => 'shahar',
  17.         'pass' => 'somesecret'
  18.     ));
  19.     $client->request(Zend_Http_Client::POST);
  20.
  21.     // Now, clear parameters and set the URI to the original one
  22.     // (note that the cookies that were set by the server are now
  23.     // stored in the jar)
  24.     $client->resetParameters();
  25.     $client->setUri('http://www.example.com/fetchdata.php');
  26. }
  27.
  28. $response = $client->request(Zend_Http_Client::GET);
  29.
  30. // Store cookies in session, for next page
  31. $_SESSION['cookiejar'] = $client->getCookieJar();

Data Streaming

By default, Zend_Http_Client accepts and returns data as PHP strings. However, in many cases there are big files to be sent or received, thus keeping them in memory might be unnecessary or too expensive. For these cases, Zend_Http_Client supports reading data from files (and in general, PHP streams) and writing data to files (streams).

In order to use stream to pass data to Zend_Http_Client, use setRawData() method with data argument being stream resource (e.g., result of fopen()).

Example #10 Sending file to HTTP server with streaming

  1. $fp = fopen("mybigfile.zip", "r");
  2. $client->setRawData($fp, 'application/zip')->request('PUT');

Only PUT requests currently support sending streams to HTTP server.

In order to receive data from the server as stream, use setStream(). Optional argument specifies the filename where the data will be stored. If the argument is just TRUE (default), temporary file will be used and will be deleted once response object is destroyed. Setting argument to FALSE disables the streaming functionality.

When using streaming, request() method will return object of class Zend_Http_Client_Response_Stream, which has two useful methods: getStreamName() will return the name of the file where the response is stored, and getStream() will return stream from which the response could be read.

You can either write the response to pre-defined file, or use temporary file for storing it and send it out or write it to another file using regular stream functions.

Example #11 Receiving file from HTTP server with streaming

  1. $client->setStreaming(); // will use temp file
  2. $response = $client->request('GET');
  3. // copy file
  4. copy($response->getStreamName(), "my/downloads/file");
  5. // use stream
  6. $fp = fopen("my/downloads/file2", "w");
  7. stream_copy_to_stream($response->getStream(), $fp);
  8. // Also can write to known file
  9. $client->setStreaming("my/downloads/myfile)->request('GET');

Zend_Http_Client - 介绍
Zend_Http
Zend Framework手册 中文版
Zend_Http_Client - Connection Adapters
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Http
  • Zend_Http_Client - 介绍
  • Zend_Http_Client - Advanced Usage
  • Zend_Http_Client - Connection Adapters
  • Zend_Http_Cookie and Zend_Http_CookieJar
  • Zend_Http_Response


Zend_Http_Cookie and Zend_Http_CookieJar - Zend Framework Manual

Zend_Http_Client - Connection Adapters
Zend_Http
Zend Framework手册 中文版
Zend_Http_Response

Zend_Http_Cookie and Zend_Http_CookieJar

Introduction

Zend_Http_Cookie, as expected, is a class that represents an HTTP cookie. It provides methods for parsing HTTP response strings, collecting cookies, and easily accessing their properties. It also allows checking if a cookie matches against a specific scenario, IE a request URL, expiration time, secure connection, etc.

Zend_Http_CookieJar is an object usually used by Zend_Http_Client to hold a set of Zend_Http_Cookie objects. The idea is that if a Zend_Http_CookieJar object is attached to a Zend_Http_Client object, all cookies going from and into the client through HTTP requests and responses will be stored by the CookieJar object. Then, when the client will send another request, it will first ask the CookieJar object for all cookies matching the request. These will be added to the request headers automatically. This is highly useful in cases where you need to maintain a user session over consecutive HTTP requests, automatically sending the session ID cookies when required. Additionally, the Zend_Http_CookieJar object can be serialized and stored in $_SESSION when needed.

Instantiating Zend_Http_Cookie Objects

Instantiating a Cookie object can be done in two ways:

  • Through the constructor, using the following syntax: new Zend_Http_Cookie(string $name, string $value, string $domain, [int $expires, [string $path, [boolean $secure]]]);

    • $name: The name of the cookie (eg. 'PHPSESSID') (required)

    • $value: The value of the cookie (required)

    • $domain: The cookie's domain (eg. '.example.com') (required)

    • $expires: Cookie expiration time, as UNIX time stamp (optional, defaults to NULL). If not set, cookie will be treated as a 'session cookie' with no expiration time.

    • $path: Cookie path, eg. '/foo/bar/' (optional, defaults to '/')

    • $secure: Boolean, Whether the cookie is to be sent over secure (HTTPS) connections only (optional, defaults to boolean FALSE)

  • By calling the fromString() static method, with a cookie string as represented in the 'Set-Cookie' HTTP response header or 'Cookie' HTTP request header. In this case, the cookie value must already be encoded. When the cookie string does not contain a 'domain' part, you must provide a reference URI according to which the cookie's domain and path will be set.

Example #1 Instantiating a Zend_Http_Cookie object

  1. // First, using the constructor. This cookie will expire in 2 hours
  2. $cookie = new Zend_Http_Cookie('foo',
  3.                                'bar',
  4.                                '.example.com',
  5.                                time() + 7200,
  6.                                '/path');
  7.
  8. // You can also take the HTTP response Set-Cookie header and use it.
  9. // This cookie is similar to the previous one, only it will not expire, and
  10. // will only be sent over secure connections
  11. $cookie = Zend_Http_Cookie::fromString('foo=bar; domain=.example.com; ' .
  12.                                        'path=/path; secure');
  13.
  14. // If the cookie's domain is not set, you have to manually specify it
  15. $cookie = Zend_Http_Cookie::fromString('foo=bar; secure;',
  16.                                        'http://www.example.com/path');

Note: When instantiating a cookie object using the Zend_Http_Cookie::fromString() method, the cookie value is expected to be URL encoded, as cookie strings should be. However, when using the constructor, the cookie value string is expected to be the real, decoded value.

A cookie object can be transferred back into a string, using the __toString() magic method. This method will produce a HTTP request "Cookie" header string, showing the cookie's name and value, and terminated by a semicolon (';'). The value will be URL encoded, as expected in a Cookie header:

Example #2 Stringifying a Zend_Http_Cookie object

  1. // Create a new cookie
  2. $cookie = new Zend_Http_Cookie('foo',
  3.                                'two words',
  4.                                '.example.com',
  5.                                time() + 7200,
  6.                                '/path');
  7.
  8. // Will print out 'foo=two+words;' :
  9. echo $cookie->__toString();
  10.
  11. // This is actually the same:
  12. echo (string) $cookie;
  13.
  14. // In PHP 5.2 and higher, this also works:
  15. echo $cookie;

Zend_Http_Cookie getter methods

Once a Zend_Http_Cookie object is instantiated, it provides several getter methods to get the different properties of the HTTP cookie:

  • string getName(): Get the name of the cookie

  • string getValue(): Get the real, decoded value of the cookie

  • string getDomain(): Get the cookie's domain

  • string getPath(): Get the cookie's path, which defaults to '/'

  • int getExpiryTime(): Get the cookie's expiration time, as UNIX time stamp. If the cookie has no expiration time set, will return NULL.

Additionally, several boolean tester methods are provided:

  • boolean isSecure(): Check whether the cookie is set to be sent over secure connections only. Generally speaking, if TRUE the cookie should only be sent over HTTPS.

  • boolean isExpired(int $time = null): Check whether the cookie is expired or not. If the cookie has no expiration time, will always return TRUE. If $time is provided, it will override the current time stamp as the time to check the cookie against.

  • boolean isSessionCookie(): Check whether the cookie is a "session cookie" - that is a cookie with no expiration time, which is meant to expire when the session ends.

Example #3 Using getter methods with Zend_Http_Cookie

  1. // First, create the cookie
  2. $cookie =
  3.     Zend_Http_Cookie::fromString('foo=two+words; ' +
  4.                                  'domain=.example.com; ' +
  5.                                  'path=/somedir; ' +
  6.                                  'secure; ' +
  7.                                  'expires=Wednesday, 28-Feb-05 20:41:22 UTC');
  8.
  9. echo $cookie->getName();   // Will echo 'foo'
  10. echo $cookie->getValue();  // will echo 'two words'
  11. echo $cookie->getDomain(); // Will echo '.example.com'
  12. echo $cookie->getPath();   // Will echo '/'
  13.
  14. echo date('Y-m-d', $cookie->getExpiryTime());
  15. // Will echo '2005-02-28'
  16.
  17. echo ($cookie->isExpired() ? 'Yes' : 'No');
  18. // Will echo 'Yes'
  19.
  20. echo ($cookie->isExpired(strtotime('2005-01-01') ? 'Yes' : 'No');
  21. // Will echo 'No'
  22.
  23. echo ($cookie->isSessionCookie() ? 'Yes' : 'No');
  24. // Will echo 'No'

Zend_Http_Cookie: Matching against a scenario

The only real logic contained in a Zend_Http_Cookie object, is in the match() method. This method is used to test a cookie against a given HTTP request scenario, in order to tell whether the cookie should be sent in this request or not. The method has the following syntax and parameters: boolean Zend_Http_Cookie->match(mixed $uri, [boolean $matchSessionCookies, [int $now]]);

  • mixed $uri: A Zend_Uri_Http object with a domain name and path to be checked. Optionally, a string representing a valid HTTP URL can be passed instead. The cookie will match if the URL's scheme (HTTP or HTTPS), domain and path all match.

  • boolean $matchSessionCookies: Whether session cookies should be matched or not. Defaults to TRUE. If set to FALSE, cookies with no expiration time will never match.

  • int $now: Time (represented as UNIX time stamp) to check a cookie against for expiration. If not specified, will default to the current time.

Example #4 Matching cookies

  1. // Create the cookie object - first, a secure session cookie
  2. $cookie = Zend_Http_Cookie::fromString('foo=two+words; ' +
  3.                                        'domain=.example.com; ' +
  4.                                        'path=/somedir; ' +
  5.                                        'secure;');
  6.
  7. $cookie->match('https://www.example.com/somedir/foo.php');
  8. // Will return true
  9.
  10. $cookie->match('http://www.example.com/somedir/foo.php');
  11. // Will return false, because the connection is not secure
  12.
  13. $cookie->match('https://otherexample.com/somedir/foo.php');
  14. // Will return false, because the domain is wrong
  15.
  16. $cookie->match('https://example.com/foo.php');
  17. // Will return false, because the path is wrong
  18.
  19. $cookie->match('https://www.example.com/somedir/foo.php', false);
  20. // Will return false, because session cookies are not matched
  21.
  22. $cookie->match('https://sub.domain.example.com/somedir/otherdir/foo.php');
  23. // Will return true
  24.
  25. // Create another cookie object - now, not secure, with expiration time
  26. // in two hours
  27. $cookie = Zend_Http_Cookie::fromString('foo=two+words; ' +
  28.                                        'domain=www.example.com; ' +
  29.                                        'expires='
  30.                                        . date(DATE_COOKIE, time() + 7200));
  31.
  32. $cookie->match('http://www.example.com/');
  33. // Will return true
  34.
  35. $cookie->match('https://www.example.com/');
  36. // Will return true - non secure cookies can go over secure connections
  37. // as well!
  38.
  39. $cookie->match('http://subdomain.example.com/');
  40. // Will return false, because the domain is wrong
  41.
  42. $cookie->match('http://www.example.com/', true, time() + (3 * 3600));
  43. // Will return false, because we added a time offset of +3 hours to
  44. // current time

The Zend_Http_CookieJar Class: Instantiation

In most cases, there is no need to directly instantiate a Zend_Http_CookieJar object. If you want to attach a new cookie jar to your Zend_Http_Client object, just call the Zend_Http_Client->setCookieJar() method, and a new, empty cookie jar will be attached to your client. You could later get this cookie jar using Zend_Http_Client->getCookieJar().

If you still wish to manually instantiate a CookieJar object, you can do so by calling "new Zend_Http_CookieJar()" directly - the constructor method does not take any parameters. Another way to instantiate a CookieJar object is to use the static Zend_Http_CookieJar::fromResponse() method. This method takes two parameters: a Zend_Http_Response object, and a reference URI, as either a string or a Zend_Uri_Http object. This method will return a new Zend_Http_CookieJar object, already containing the cookies set by the passed HTTP response. The reference URI will be used to set the cookie's domain and path, if they are not defined in the Set-Cookie headers.

Adding Cookies to a Zend_Http_CookieJar object

Usually, the Zend_Http_Client object you attached your CookieJar object to will automatically add cookies set by HTTP responses to your jar. If you wish to manually add cookies to your jar, this can be done by using two methods:

  • Zend_Http_CookieJar->addCookie($cookie[, $ref_uri]): Add a single cookie to the jar. $cookie can be either a Zend_Http_Cookie object or a string, which will be converted automatically into a Cookie object. If a string is provided, you should also provide $ref_uri - which is a reference URI either as a string or Zend_Uri_Http object, to use as the cookie's default domain and path.

  • Zend_Http_CookieJar->addCookiesFromResponse($response, $ref_uri): Add all cookies set in a single HTTP response to the jar. $response is expected to be a Zend_Http_Response object with Set-Cookie headers. $ref_uri is the request URI, either as a string or a Zend_Uri_Http object, according to which the cookies' default domain and path will be set.

Retrieving Cookies From a Zend_Http_CookieJar object

Just like with adding cookies, there is usually no need to manually fetch cookies from a CookieJar object. Your Zend_Http_Client object will automatically fetch the cookies required for an HTTP request for you. However, you can still use 3 provided methods to fetch cookies from the jar object: getCookie(), getAllCookies(), and getMatchingCookies(). Additionnaly, iterating over the CookieJar will let you retrieve all the Zend_Http_Cookie objects from it.

It is important to note that each one of these methods takes a special parameter, which sets the return type of the method. This parameter can have 3 values:

  • Zend_Http_CookieJar::COOKIE_OBJECT: Return a Zend_Http_Cookie object. If the method returns more than one cookie, an array of objects will be returned.

  • Zend_Http_CookieJar::COOKIE_STRING_ARRAY: Return cookies as strings, in a "foo=bar" format, suitable for sending in a HTTP request "Cookie" header. If more than one cookie is returned, an array of strings is returned.

  • Zend_Http_CookieJar::COOKIE_STRING_CONCAT: Similar to COOKIE_STRING_ARRAY, but if more than one cookie is returned, this method will concatenate all cookies into a single, long string separated by semicolons (;), and return it. This is especially useful if you want to directly send all matching cookies in a single HTTP request "Cookie" header.

The structure of the different cookie-fetching methods is described below:

  • Zend_Http_CookieJar->getCookie($uri, $cookie_name[, $ret_as]): Get a single cookie from the jar, according to its URI (domain and path) and name. $uri is either a string or a Zend_Uri_Http object representing the URI. $cookie_name is a string identifying the cookie name. $ret_as specifies the return type as described above. $ret_type is optional, and defaults to COOKIE_OBJECT.

  • Zend_Http_CookieJar->getAllCookies($ret_as): Get all cookies from the jar. $ret_as specifies the return type as described above. If not specified, $ret_type defaults to COOKIE_OBJECT.

  • Zend_Http_CookieJar->getMatchingCookies($uri[, $matchSessionCookies[, $ret_as[, $now]]]): Get all cookies from the jar that match a specified scenario, that is a URI and expiration time.

    • $uri is either a Zend_Uri_Http object or a string specifying the connection type (secure or non-secure), domain and path to match against.

    • $matchSessionCookies is a boolean telling whether to match session cookies or not. Session cookies are cookies that have no specified expiration time. Defaults to TRUE.

    • $ret_as specifies the return type as described above. If not specified, defaults to COOKIE_OBJECT.

    • $now is an integer representing the UNIX time stamp to consider as "now" - that is any cookies who are set to expire before this time will not be matched. If not specified, defaults to the current time.

    You can read more about cookie matching here: Zend_Http_Cookie: Matching against a scenario.

Zend_Http_Client - Connection Adapters
Zend_Http
Zend Framework手册 中文版
Zend_Http_Response
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Http
  • Zend_Http_Client - 介绍
  • Zend_Http_Client - Advanced Usage
  • Zend_Http_Client - Connection Adapters
  • Zend_Http_Cookie and Zend_Http_CookieJar
  • Zend_Http_Response


Zend_Http_Response - Zend Framework Manual

Zend_Http_Cookie and Zend_Http_CookieJar
Zend_Http
Zend Framework手册 中文版
Zend_InfoCard

Zend_Http_Response

简介

对于由Zend_Http_Client - 介绍返回的应答(Response)信息，Zend_Http_Response 可以提供简单的访问方式。 它提供一组友好的方法来获得从请求返回的应答信息:

  • isError(): 如果收到HTTP出错状态的代码,返回TRUE, 否则返回FALSE.

  • isSuccessful(): 如果得到HTTP请求成功的状态代码,返回TRUE, 否则返回FALSE.

  • isRedirect(): 如果得到HTTP重定向的状态代码,返回TRUE, 否则返回FALSE.

  • getStatus(): 返回HTTP请求的状态代码.

  • getHeaders(): 以数组的形式返回HTTP请求头部信息的字符串.

  • getBody(): 返回HTTP正文内容(字符串).

Example #1 处理HTTP应答

<?php
require_once 'Zend/Http/Client.php';
try {
    $http = new Zend_Http_Client('http://example.org');
    $response = $http->get();
    if ($response->isSuccessful()) {
        echo $response->getBody();
    } else {
        echo "<p>发生错误</p>\n";
        echo "HTTP Status: " . $response->getStatus() . "\n";
        echo "HTTP Headers:\n";
        $responseHeaders = $response->getHeaders();
        foreach ($responseHeaders as $responseHeaderName => $responseHeaderValue) {
            echo "$responseHeaderName: $responseHeaderValue\n";
        }
    }
} catch (Zend_Http_Client_Exception $e) {
    echo '<p>An error occurred (' .$e->getMessage(). ')</p>';
}
?>
Zend_Http_Cookie and Zend_Http_CookieJar
Zend_Http
Zend Framework手册 中文版
Zend_InfoCard
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Http
  • Zend_Http_Client - 介绍
  • Zend_Http_Client - Advanced Usage
  • Zend_Http_Client - Connection Adapters
  • Zend_Http_Cookie and Zend_Http_CookieJar
  • Zend_Http_Response


Zend_InfoCard - Zend Framework Manual

Zend_Http_Response
Zend Framework Reference
Zend Framework手册 中文版
Introduction

Zend_InfoCard

Table of Contents
  • Introduction
Zend_Http_Response
Zend Framework Reference
Zend Framework手册 中文版
Introduction
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


Introduction - Zend Framework Manual

Zend_InfoCard
Zend_InfoCard
Zend Framework手册 中文版
Zend_Json

Introduction

The Zend_InfoCard component implements relying-party support for Information Cards. Information Cards are used for identity management on the internet and authentication of users to web sites. The web sites that the user ultimately authenticates to are called relying-parties.

Detailed information about information cards and their importance to the internet identity metasystem can be found on the » IdentityBlog.

Basic Theory of Usage

Usage of Zend_InfoCard can be done one of two ways: either as part of the larger Zend_Auth component via the Zend_InfoCard authentication adapter or as a stand-alone component. In both cases an information card can be requested from a user by using the following HTML block in your HTML login form:

  1. <form action="http://example.com/server" method="POST">
  2.   <input type='image' src='/images/ic.png' align='center'
  3.         width='120px' style='cursor:pointer' />
  4.   <object type="application/x-informationCard"
  5.           name="xmlToken">
  6.    <param name="tokenType"
  7.          value="urn:oasis:names:tc:SAML:1.0:assertion" />
  8.    <param name="requiredClaims"
  9.          value="http://.../claims/privatepersonalidentifier
  10.          http://.../claims/givenname
  11.          http://.../claims/surname" />
  12.  </object>
  13. </form>

In the example above, the requiredClaims <param> tag is used to identify pieces of information known as claims (i.e. person's first name, last name) which the web site (a.k.a "relying party") needs in order a user to authenticate using an information card. For your reference, the full URI (for instance the givenname claim) is as follows: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname

When the above HTML is activated by a user (clicks on it), the browser will bring up a card selection program which not only shows them which information cards meet the requirements of the site, but also allows them to select which information card to use if multiple meet the criteria. This information card is transmitted as an XML document to the specified POST URL and is ready to be processed by the Zend_InfoCard component.

Note, Information cards can only be HTTP POSTed to SSL-encrypted URLs. Please consult your web server's documentation on how to set up SSL encryption.

Using as part of Zend_Auth

In order to use the component as part of the Zend_Auth authentication system, you must use the provided Zend_Auth_Adapter_InfoCard to do so (not available in the standalone Zend_InfoCard distribution). An example of its usage is shown below:

  1. <?php
  2. if (isset($_POST['xmlToken'])) {
  3.
  4.     $adapter = new Zend_Auth_Adapter_InfoCard($_POST['xmlToken']);
  5.
  6.     $adapter->addCertificatePair('/usr/local/Zend/apache2/conf/server.key',
  7.                                  '/usr/local/Zend/apache2/conf/server.crt');
  8.
  9.     $auth = Zend_Auth::getInstance();
  10.
  11.     $result = $auth->authenticate($adapter);
  12.
  13.     switch ($result->getCode()) {
  14.         case Zend_Auth_Result::SUCCESS:
  15.             $claims = $result->getIdentity();
  16.             print "Given Name: {$claims->givenname}<br />";
  17.             print "Surname: {$claims->surname}<br />";
  18.             print "Email Address: {$claims->emailaddress}<br />";
  19.             print "PPI: {$claims->getCardID()}<br />";
  20.             break;
  21.         case Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID:
  22.             print "The Credential you provided did not pass validation";
  23.             break;
  24.         default:
  25.         case Zend_Auth_Result::FAILURE:
  26.             print "There was an error processing your credentials.";
  27.             break;
  28.     }
  29.
  30.     if (count($result->getMessages()) > 0) {
  31.         print "<pre>";
  32.         var_dump($result->getMessages());
  33.         print "</pre>";
  34.     }
  35.
  36. }
  37. ?>
  38. <hr />
  39. <div id="login" style="font-family: arial; font-size: 2em;">
  40. <p>Simple Login Demo</p>
  41.  <form method="post">
  42.   <input type="submit" value="Login" />
  43.    <object type="application/x-informationCard" name="xmlToken">
  44.     <param name="tokenType"
  45.           value="urn:oasis:names:tc:SAML:1.0:assertion" />
  46.     <param name="requiredClaims"
  47.           value="http://.../claims/givenname
  48.                  http://.../claims/surname
  49.                  http://.../claims/emailaddress
  50.                  http://.../claims/privatepersonalidentifier" />
  51.   </object>
  52.  </form>
  53. </div>

In the example above, we first create an instance of the Zend_Auth_Adapter_InfoCard and pass the XML data posted by the card selector into it. Once an instance has been created you must then provide at least one SSL certificate public/private key pair used by the web server that received the HTTP POST. These files are used to validate the destination of the information posted to the server and are a requirement when using Information Cards.

Once the adapter has been configured, you can then use the standard Zend_Auth facilities to validate the provided information card token and authenticate the user by examining the identity provided by the getIdentity() method.

Using the Zend_InfoCard component standalone

It is also possible to use the Zend_InfoCard component as a standalone component by interacting with the Zend_InfoCard class directly. Using the Zend_InfoCard class is very similar to its use with the Zend_Auth component. An example of its use is shown below:

  1. <?php
  2. if (isset($_POST['xmlToken'])) {
  3.     $infocard = new Zend_InfoCard();
  4.     $infocard->addCertificatePair('/usr/local/Zend/apache2/conf/server.key',
  5.                                   '/usr/local/Zend/apache2/conf/server.crt');
  6.
  7.     $claims = $infocard->process($_POST['xmlToken']);
  8.
  9.     if($claims->isValid()) {
  10.         print "Given Name: {$claims->givenname}<br />";
  11.         print "Surname: {$claims->surname}<br />";
  12.         print "Email Address: {$claims->emailaddress}<br />";
  13.         print "PPI: {$claims->getCardID()}<br />";
  14.     } else {
  15.         print "Error Validating identity: {$claims->getErrorMsg()}";
  16.     }
  17. }
  18. ?>
  19. <hr />
  20. <div id="login" style="font-family: arial; font-size: 2em;">
  21.  <p>Simple Login Demo</p>
  22.  <form method="post">
  23.   <input type="submit" value="Login" />
  24.    <object type="application/x-informationCard" name="xmlToken">
  25.     <param name="tokenType"
  26.           value="urn:oasis:names:tc:SAML:1.0:assertion" />
  27.     <param name="requiredClaims"
  28.           value="http://.../claims/givenname
  29.                  http://.../claims/surname
  30.                  http://.../claims/emailaddress
  31.                  http://.../claims/privatepersonalidentifier" />
  32.    </object>
  33.  </form>
  34. </div>

In the example above, we use the Zend_InfoCard component independently to validate the token provided by the user. As was the case with the Zend_Auth_Adapter_InfoCard, we create an instance of Zend_InfoCard and then set one or more SSL certificate public/private key pairs used by the web server. Once configured, we can use the process() method to process the information card and return the results.

Working with a Claims object

Regardless of whether the Zend_InfoCard component is used as a standalone component or as part of Zend_Auth via Zend_Auth_Adapter_InfoCard, the ultimate result of the processing of an information card is a Zend_InfoCard_Claims object. This object contains the assertions (a.k.a. claims) made by the submitting user based on the data requested by your web site when the user authenticated. As shown in the examples above, the validity of the information card can be ascertained by calling the Zend_InfoCard_Claims::isValid() method. Claims themselves can either be retrieved by simply accessing the identifier desired (i.e. givenname) as a property of the object or through the getClaim() method.

In most cases you will never need to use the getClaim() method. However, if your requiredClaims mandate that you request claims from multiple different sources/namespaces then you will need to extract them explicitly using this method (simply pass it the full URI of the claim to retrieve its value from within the information card). Generally speaking however, the Zend_InfoCard component will set the default URI for claims to be the one used the most frequently within the information card itself and the simplified property-access method can be used.

As part of the validation process, it is the developer's responsibility to examine the issuing source of the claims contained within the information card and to decide if that source is a trusted source of information. To do so, the getIssuer() method is provided within the Zend_InfoCard_Claims object which returns the URI of the issuer of the information card claims.

Attaching Information Cards to existing accounts

It is possible to add support for information cards to an existing authentication system by storing the private personal identifier (PPI) to a previously traditionally-authenticated account and including at least the http://schemas.xmlsoap.org/ws/2005/05/identity/claims/privatepersonalidentifier claim as part of the requiredClaims of the request. If this claim is requested then the Zend_InfoCard_Claims object will provide a unique identifier for the specific card that was submitted by calling the getCardID() method.

An example of how to attach an information card to an existing traditional-authentication account is shown below:

  1. // ...
  2. public function submitinfocardAction()
  3. {
  4.     if (!isset($_REQUEST['xmlToken'])) {
  5.         throw new ZBlog_Exception('Expected an encrypted token ' .
  6.                                   'but was not provided');
  7.     }
  8.
  9.     $infoCard = new Zend_InfoCard();
  10.     $infoCard->addCertificatePair(SSL_CERTIFICATE_PRIVATE,
  11.                                   SSL_CERTIFICATE_PUB);
  12.
  13.     try {
  14.         $claims = $infoCard->process($request['xmlToken']);
  15.     } catch(Zend_InfoCard_Exception $e) {
  16.         // TODO Error processing your request
  17.         throw $e;
  18.     }
  19.
  20.     if ($claims->isValid()) {
  21.         $db = ZBlog_Data::getAdapter();
  22.
  23.         $ppi = $db->quote($claims->getCardID());
  24.         $fullname = $db->quote("{$claims->givenname} {$claims->surname}");
  25.
  26.         $query = "UPDATE blogusers
  27.                      SET ppi = $ppi,
  28.                          real_name = $fullname
  29.                    WHERE username='administrator'";
  30.
  31.         try {
  32.             $db->query($query);
  33.         } catch(Exception $e) {
  34.             // TODO Failed to store in DB
  35.         }
  36.
  37.         $this->view->render();
  38.         return;
  39.     } else {
  40.         throw new
  41.             ZBlog_Exception("Infomation card failed security checks");
  42.     }
  43. }

Creating Zend_InfoCard Adapters

The Zend_InfoCard component was designed to allow for growth in the information card standard through the use of a modular architecture. At this time, many of these hooks are unused and can be ignored, but there is one class that should be written for any serious information card implementation: the Zend_InfoCard adapter.

The Zend_InfoCard adapter is used as a callback mechanism within the component to perform various tasks, such as storing and retrieving Assertion IDs for information cards when they are processed by the component. While storing the assertion IDs of submitted information cards is not necessary, failing to do so opens up the possibility of the authentication scheme being compromised through a replay attack.

To prevent this, one must implement the Zend_InfoCard_Adapter_Interface and set an instance of this interface prior to calling either the process() (standalone) or authenticate() method as a Zend_Auth adapter. To set this interface, the setAdapter() method should be used. In the example below, we set a Zend_InfoCard adapter and use it in our application:

  1. class myAdapter implements Zend_InfoCard_Adapter_Interface
  2. {
  3.     public function storeAssertion($assertionURI,
  4.                                    $assertionID,
  5.                                    $conditions)
  6.     {
  7.         /* Store the assertion and its conditions by ID and URI */
  8.     }
  9.
  10.     public function retrieveAssertion($assertionURI, $assertionID)
  11.     {
  12.         /* Retrieve the assertion by URI and ID */
  13.     }
  14.
  15.     public function removeAssertion($assertionURI, $assertionID)
  16.     {
  17.         /* Delete a given assertion by URI/ID */
  18.     }
  19. }
  20.
  21. $adapter  = new myAdapter();
  22.
  23. $infoCard = new Zend_InfoCard();
  24. $infoCard->addCertificatePair(SSL_PRIVATE, SSL_PUB);
  25. $infoCard->setAdapter($adapter);
  26.
  27. $claims = $infoCard->process($_POST['xmlToken']);
Zend_InfoCard
Zend_InfoCard
Zend Framework手册 中文版
Zend_Json
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_InfoCard
  • Introduction


Zend_Json - Zend Framework Manual

Introduction
Zend Framework Reference
Zend Framework手册 中文版
简介

Zend_Json

Table of Contents
  • 简介
  • 基本用法
  • JSON 对象
  • XML 到 JSON 转换
  • Zend_Json_Server - JSON-RPC server
Introduction
Zend Framework Reference
Zend Framework手册 中文版
简介
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


简介 - Zend Framework Manual

Zend_Json
Zend_Json
Zend Framework手册 中文版
基本用法

简介

Zend_Json 提供一个方便的方式来串联(native的)PHP(的变量)和JSON，并将JSON(对象)解码到PHP中。 关于JSON的更多信息， » 请参考 JSON 项目网站。

JSON, JavaScript Object Notation, 可以被应用于JS和其他语言的轻量级数据交换。 因为JSON(对象)可以直接被Javascript执行，对于web2.0接口来说,它是一种理想的格式；它是使用XML作为AJAX接口的一个更简单的替换方案。

另外，Zend_Json 提供把字符串从任意的 XML 格式转换到 JSON 格式。这个内置的功能使 PHP 开发者能够在把企业数据发送到基于浏览器的 Ajax客户程序之前把它（企业数据）从 XML 格式转换到 JSON 格式。它提供了简便的方法在服务器端做动态数据转换，因而避免了在浏览器端进行不必要的 XML 解析。 它提供了很好的实用函数，能够容易地实现 application-specific 数据处理技术。

Zend_Json
Zend_Json
Zend Framework手册 中文版
基本用法
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Json
  • 简介
  • 基本用法
  • JSON 对象
  • XML 到 JSON 转换
  • Zend_Json_Server - JSON-RPC server


基本用法 - Zend Framework Manual

简介
Zend_Json
Zend Framework手册 中文版
JSON 对象

基本用法

Zend_Json的使用包括使用现有的两个公共的static方法 : Zend_Json::encode() 和 Zend_Json::decode().

// 获得一个value:
$phpNative = Zend_Json::decode($encodedValue);

// 编码并返回给客户端:
$json = Zend_Json::encode($phpNative);

简介
Zend_Json
Zend Framework手册 中文版
JSON 对象
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Json
  • 简介
  • 基本用法
  • JSON 对象
  • XML 到 JSON 转换
  • Zend_Json_Server - JSON-RPC server


JSON 对象 - Zend Framework Manual

基本用法
Zend_Json
Zend Framework手册 中文版
XML 到 JSON 转换

JSON 对象

当编码PHP对象为JSON时, 它的所有的公有属性将被编码为JSON格式（到JSON对象中）.

JSON 不允许 object references，所以注意不要带递归 references 解码对象（ objects）。 如果递归有问题，Zend_Json::encode() 和 Zend_Json_Encoder::encode() 允许一个可选的第二个参数来检查递归；如果对象被系列化两次就抛出异常。

解码JSON对象貌似有一点轻微的难度， 因为Javascript对象与PHP的联合数组的结构更相近。 尽管如此， 一些人建议应该传入一个类的定义，然后类的实例应该由JSON的key/value对来被建造和组装； 另外有人这样做会引发一些安全问题。

默认情况下， Zend_Json 将解码JSON对象作为关联数组。但是如果你希望它返回一个对象， 以可以这样来指定：

// 解码 JSON 对象作为 PHP 对象
$phpNative = Zend_Json::decode($encodedValue, Zend_Json::TYPE_OBJECT);

这样任何解码后的对象将被作为一个StdClass的对象来返回，对象带有根据JSON对象的key/value对生成的一系列属性。

Zend Framework推荐每个开发者应该决定怎样来解码JSON对象。 如果一个特定类型的对象需要被构建，它可以由开发者的代码创建，然后用 Zend_Json 解码后的值来组装。

基本用法
Zend_Json
Zend Framework手册 中文版
XML 到 JSON 转换
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Json
  • 简介
  • 基本用法
  • JSON 对象
  • XML 到 JSON 转换
  • Zend_Json_Server - JSON-RPC server


XML 到 JSON 转换 - Zend Framework Manual

JSON 对象
Zend_Json
Zend Framework手册 中文版
Zend_Json_Server - JSON-RPC server

XML 到 JSON 转换

提供了方便的方法来转换数据格式从 XML 到 JSON。这个功能从一篇 » IBM developerWorks 文章 的到启发。

Zend_Json 包括一个叫做 Zend_Json::fromXml() 的静态方法，它将从给定的 XML 的输入生成 JSON。它用任何任意的 XML 字符串作为输入参数；它也带有一个可选的布尔输入参数来指示转换逻辑在转换过程中是否忽略 XML 属性，如果没有给出这个参数，那么缺省的行为就是忽略 XML 属性。本函数的调用示范如下：

        // fromXml function simply takes a String containing XML contents as input.
        $jsonContents = Zend_Json::fromXml($xmlStringContents, true);?>

Zend_Json::fromXml() 函数执行 XML 格式的字符串输入和返回等同的 JSON 格式字符串的输出的转换，如果有任何 XML 输入格式错误或者转换逻辑错误，它将抛出一个异常。转换逻辑也使用递归技术来遍历 XML 树，它支持 25 级递归，如果递归超过这个深度，它将抛出一个 Zend_Json_Exception 。在 Zend Framework 的测试目录里有若干不同复杂度的 XML 文件，可用来测试 xml2json 功能。

下面一个简单的例子来示例被传递的 XML 输入字符串和从 Zend_Json::fromXml() 函数返回的 JSON 字符串。本例使用可选的参数控制在转换过程中不忽略 XML 属性，因此，你会注意到在 JSON 结果字符串中包含了在 XML 输入字符串中的 XML 属性的表达。

XML 输入字符串传递给 Zend_Json::fromXml() 函数：

<?xml version="1.0" encoding="UTF-8"?>
<books>
    <book id="1">
        <title>Code Generation in Action</title>
        <author><first>Jack</first><last>Herrington</last></author>
        <publisher>Manning</publisher>
    </book>

    <book id="2">
        <title>PHP Hacks</title>
        <author><first>Jack</first><last>Herrington</last></author>
        <publisher>O'Reilly</publisher>
    </book>

    <book id="3">
        <title>Podcasting Hacks</title>
        <author><first>Jack</first><last>Herrington</last></author>
        <publisher>O'Reilly</publisher>
    </book>
</books> ?>

从 Zend_Json::fromXml() 函数返回的 JSON 输出字符串:

{
   "books" : {
      "book" : [ {
         "@attributes" : {
            "id" : "1"
         },
         "title" : "Code Generation in Action",
         "author" : {
            "first" : "Jack", "last" : "Herrington"
         },
         "publisher" : "Manning"
      }, {
         "@attributes" : {
            "id" : "2"
         },
         "title" : "PHP Hacks", "author" : {
            "first" : "Jack", "last" : "Herrington"
         },
         "publisher" : "O'Reilly"
      }, {
         "@attributes" : {
            "id" : "3"
         },
         "title" : "Podcasting Hacks", "author" : {
            "first" : "Jack", "last" : "Herrington"
         },
         "publisher" : "O'Reilly"
      }
   ]}
}  ?>

关于 xml2json 特性的更多信息和以从它自己原始的提案中找到：» Zend_xml2json 提案 。

JSON 对象
Zend_Json
Zend Framework手册 中文版
Zend_Json_Server - JSON-RPC server
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Json
  • 简介
  • 基本用法
  • JSON 对象
  • XML 到 JSON 转换
  • Zend_Json_Server - JSON-RPC server


Zend_Json_Server - JSON-RPC server - Zend Framework Manual

XML 到 JSON 转换
Zend_Json
Zend Framework手册 中文版
Zend_Layout

Zend_Json_Server - JSON-RPC server

Zend_Json_Server is a » JSON-RPC server implementation. It supports both the » JSON-RPC version 1 specification as well as the » version 2 specification; additionally, it provides a PHP implementation of the » Service Mapping Description (SMD) specification for providing service metadata to service consumers.

JSON-RPC is a lightweight Remote Procedure Call protocol that utilizes JSON for its messaging envelopes. This JSON-RPC implementation follows PHP's » SoapServer API. This means, in a typical situation, you will simply:

  • Instantiate the server object

  • Attach one or more functions and/or classes/objects to the server object

  • handle() the request

Zend_Json_Server utilizes Zend_Server_Reflection to perform reflection on any attached classes or functions, and uses that information to build both the SMD and enforce method call signatures. As such, it is imperative that any attached functions and/or class methods have full PHP docblocks documenting, minimally:

  • All parameters and their expected variable types

  • The return value variable type

Zend_Json_Server listens for POST requests only at this time; fortunately, most JSON-RPC client implementations in the wild at the time of this writing will only POST requests as it is. This makes it simple to utilize the same server end point to both handle requests as well as to deliver the service SMD, as is shown in the next example.

Example #1 Zend_Json_Server Usage

First, let's define a class we wish to expose via the JSON-RPC server. We'll call the class 'Calculator', and define methods for 'add', 'subtract', 'multiply', and 'divide':

  1. /**
  2. * Calculator - sample class to expose via JSON-RPC
  3. */
  4. class Calculator
  5. {
  6.     /**
  7.      * Return sum of two variables
  8.      *
  9.      * @param  int $x
  10.      * @param  int $y
  11.      * @return int
  12.      */
  13.     public function add($x, $y)
  14.     {
  15.         return $x + $y;
  16.     }
  17.
  18.     /**
  19.      * Return difference of two variables
  20.      *
  21.      * @param  int $x
  22.      * @param  int $y
  23.      * @return int
  24.      */
  25.     public function subtract($x, $y)
  26.     {
  27.         return $x - $y;
  28.     }
  29.
  30.     /**
  31.      * Return product of two variables
  32.      *
  33.      * @param  int $x
  34.      * @param  int $y
  35.      * @return int
  36.      */
  37.     public function multiply($x, $y)
  38.     {
  39.         return $x * $y;
  40.     }
  41.
  42.     /**
  43.      * Return the division of two variables
  44.      *
  45.      * @param  int $x
  46.      * @param  int $y
  47.      * @return float
  48.      */
  49.     public function divide($x, $y)
  50.     {
  51.         return $x / $y;
  52.     }
  53. }

Note that each method has a docblock with entries indicating each parameter and its type, as well as an entry for the return value. This is absolutely critical when utilizing Zend_Json_Server or any other server component in Zend Framework, for that matter.

Now we'll create a script to handle the requests:

  1. $server = new Zend_Json_Server();
  2.
  3. // Indicate what functionality is available:
  4. $server->setClass('Calculator');
  5.
  6. // Handle the request:
  7. $server->handle();

However, this will not address the issue of returning an SMD so that the JSON-RPC client can autodiscover methods. That can be accomplished by determining the HTTP request method, and then specifying some server metadata:

  1. $server = new Zend_Json_Server();
  2. $server->setClass('Calculator');
  3.
  4. if ('GET' == $_SERVER['REQUEST_METHOD']) {
  5.     // Indicate the URL endpoint, and the JSON-RPC version used:
  6.     $server->setTarget('/json-rpc.php')
  7.            ->setEnvelope(Zend_Json_Server_Smd::ENV_JSONRPC_2);
  8.
  9.     // Grab the SMD
  10.     $smd = $server->getServiceMap();
  11.
  12.     // Return the SMD to the client
  13.     header('Content-Type: application/json');
  14.     echo $smd;
  15.     return;
  16. }
  17.
  18. $server->handle();

If utilizing the JSON-RPC server with Dojo toolkit, you will also need to set a special compatibility flag to ensure that the two interoperate properly:

  1. $server = new Zend_Json_Server();
  2. $server->setClass('Calculator');
  3.
  4. if ('GET' == $_SERVER['REQUEST_METHOD']) {
  5.     $server->setTarget('/json-rpc.php')
  6.            ->setEnvelope(Zend_Json_Server_Smd::ENV_JSONRPC_2);
  7.     $smd = $server->getServiceMap();
  8.
  9.     // Set Dojo compatibility:
  10.     $smd->setDojoCompatible(true);
  11.
  12.     header('Content-Type: application/json');
  13.     echo $smd;
  14.     return;
  15. }
  16.
  17. $server->handle();

Advanced Details

While most functionality for Zend_Json_Server is spelled out in Zend_Json_Server Usage, more advanced functionality is available.

Zend_Json_Server

Zend_Json_Server is the core class in the JSON-RPC offering; it handles all requests and returns the response payload. It has the following methods:

  • addFunction($function): Specify a userland function to attach to the server.

  • setClass($class): Specify a class or object to attach to the server; all public methods of that item will be exposed as JSON-RPC methods.

  • fault($fault = null, $code = 404, $data = null): Create and return a Zend_Json_Server_Error object.

  • handle($request = false): Handle a JSON-RPC request; optionally, pass a Zend_Json_Server_Request object to utilize (creates one by default).

  • getFunctions(): Return a list of all attached methods.

  • setRequest(Zend_Json_Server_Request $request): Specify a request object for the server to utilize.

  • getRequest(): Retrieve the request object used by the server.

  • setResponse(Zend_Json_Server_Response $response): Set the response object for the server to utilize.

  • getResponse(): Retrieve the response object used by the server.

  • setAutoEmitResponse($flag): Indicate whether the server should automatically emit the response and all headers; by default, this is TRUE.

  • autoEmitResponse(): Determine if auto-emission of the response is enabled.

  • getServiceMap(): Retrieve the service map description in the form of a Zend_Json_Server_Smd object

Zend_Json_Server_Request

The JSON-RPC request environment is encapsulated in the Zend_Json_Server_Request object. This object allows you to set necessary portions of the JSON-RPC request, including the request ID, parameters, and JSON-RPC specification version. It has the ability to load itself via JSON or a set of options, and can render itself as JSON via the toJson() method.

The request object has the following methods available:

  • setOptions(array $options): Specify object configuration. $options may contain keys matching any 'set' method: setParams(), setMethod(), setId(), and setVersion().

  • addParam($value, $key = null): Add a parameter to use with the method call. Parameters can be just the values, or can optionally include the parameter name.

  • addParams(array $params): Add multiple parameters at once; proxies to addParam()

  • setParams(array $params): Set all parameters at once; overwrites any existing parameters.

  • getParam($index): Retrieve a parameter by position or name.

  • getParams(): Retrieve all parameters at once.

  • setMethod($name): Set the method to call.

  • getMethod(): Retrieve the method that will be called.

  • isMethodError(): Determine whether or not the request is malformed and would result in an error.

  • setId($name): Set the request identifier (used by the client to match requests to responses).

  • getId(): Retrieve the request identifier.

  • setVersion($version): Set the JSON-RPC specification version the request conforms to. May be either '1.0' or '2.0'.

  • getVersion(): Retrieve the JSON-RPC specification version used by the request.

  • loadJson($json): Load the request object from a JSON string.

  • toJson(): Render the request as a JSON string.

An HTTP specific version is available via Zend_Json_Server_Request_Http. This class will retrieve the request via php://input, and allows access to the raw JSON via the getRawJson() method.

Zend_Json_Server_Response

The JSON-RPC response payload is encapsulated in the Zend_Json_Server_Response object. This object allows you to set the return value of the request, whether or not the response is an error, the request identifier, the JSON-RPC specification version the response conforms to, and optionally the service map.

The response object has the following methods available:

  • setResult($value): Set the response result.

  • getResult(): Retrieve the response result.

  • setError(Zend_Json_Server_Error $error): Set an error object. If set, this will be used as the response when serializing to JSON.

  • getError(): Retrieve the error object, if any.

  • isError(): Whether or not the response is an error response.

  • setId($name): Set the request identifier (so the client may match the response with the original request).

  • getId(): Retrieve the request identifier.

  • setVersion($version): Set the JSON-RPC version the response conforms to.

  • getVersion(): Retrieve the JSON-RPC version the response conforms to.

  • toJson(): Serialize the response to JSON. If the response is an error response, serializes the error object.

  • setServiceMap($serviceMap): Set the service map object for the response.

  • getServiceMap(): Retrieve the service map object, if any.

An HTTP specific version is available via Zend_Json_Server_Response_Http. This class will send the appropriate HTTP headers as well as serialize the response as JSON.

Zend_Json_Server_Error

JSON-RPC has a special format for reporting error conditions. All errors need to provide, minimally, an error message and error code; optionally, they can provide additional data, such as a backtrace.

Error codes are derived from those recommended by » the XML-RPC EPI project. Zend_Json_Server appropriately assigns the code based on the error condition. For application exceptions, the code '-32000' is used.

Zend_Json_Server_Error exposes the following methods:

  • setCode($code): Set the error code; if the code is not in the accepted XML-RPC error code range, -32000 will be assigned.

  • getCode(): Retrieve the current error code.

  • setMessage($message): Set the error message.

  • getMessage(): Retrieve the current error message.

  • setData($data): Set auxiliary data further qualifying the error, such as a backtrace.

  • getData(): Retrieve any current auxiliary error data.

  • toArray(): Cast the error to an array. The array will contain the keys 'code', 'message', and 'data'.

  • toJson(): Cast the error to a JSON-RPC error representation.

Zend_Json_Server_Smd

SMD stands for Service Mapping Description, a JSON schema that defines how a client can interact with a particular web service. At the time of this writing, the » specification has not yet been formally ratified, but it is in use already within Dojo toolkit as well as other JSON-RPC consumer clients.

At its most basic, a Service Mapping Description indicates the method of transport (POST, GET, TCP/IP, etc), the request envelope type (usually based on the protocol of the server), the target URL of the service provider, and a map of services available. In the case of JSON-RPC, the service map is a list of available methods, which each method documenting the available parameters and their types, as well as the expected return value type.

Zend_Json_Server_Smd provides an object oriented way to build service maps. At its most basic, you pass it metadata describing the service using mutators, and specify services (methods and functions).

The service descriptions themselves are typically instances of Zend_Json_Server_Smd_Service; you can also pass all information as an array to the various service mutators in Zend_Json_Server_Smd, and it will instantiate a service object for you. The service objects contain information such as the name of the service (typically the function or method name), the parameters (names, types, and position), and the return value type. Optionally, each service can have its own target and envelope, though this functionality is rarely used.

Zend_Json_Server actually does all of this behind the scenes for you, by using reflection on the attached classes and functions; you should create your own service maps only if you need to provide custom functionality that class and function introspection cannot offer.

Methods available in Zend_Json_Server_Smd include:

  • setOptions(array $options): Setup an SMD object from an array of options. All mutators (methods beginning with 'set') can be used as keys.

  • setTransport($transport): Set the transport used to access the service; only POST is currently supported.

  • getTransport(): Get the current service transport.

  • setEnvelope($envelopeType): Set the request envelope that should be used to access the service. Currently, supports the constants Zend_Json_Server_Smd::ENV_JSONRPC_1 and Zend_Json_Server_Smd::ENV_JSONRPC_2.

  • getEnvelope(): Get the current request envelope.

  • setContentType($type): Set the content type requests should use (by default, this is 'application/json').

  • getContentType(): Get the current content type for requests to the service.

  • setTarget($target): Set the URL endpoint for the service.

  • getTarget(): Get the URL endpoint for the service.

  • setId($id): Typically, this is the URL endpoint of the service (same as the target).

  • getId(): Retrieve the service ID (typically the URL endpoint of the service).

  • setDescription($description): Set a service description (typically narrative information describing the purpose of the service).

  • getDescription(): Get the service description.

  • setDojoCompatible($flag): Set a flag indicating whether or not the SMD is compatible with Dojo toolkit. When TRUE, the generated JSON SMD will be formatted to comply with the format that Dojo's JSON-RPC client expects.

  • isDojoCompatible(): Returns the value of the Dojo compatibility flag (FALSE, by default).

  • addService($service): Add a service to the map. May be an array of information to pass to the constructor of Zend_Json_Server_Smd_Service, or an instance of that class.

  • addServices(array $services): Add multiple services at once.

  • setServices(array $services): Add multiple services at once, overwriting any previously set services.

  • getService($name): Get a service by its name.

  • getServices(): Get all attached services.

  • removeService($name): Remove a service from the map.

  • toArray(): Cast the service map to an array.

  • toDojoArray(): Cast the service map to an array compatible with Dojo Toolkit.

  • toJson(): Cast the service map to a JSON representation.

Zend_Json_Server_Smd_Service has the following methods:

  • setOptions(array $options): Set object state from an array. Any mutator (methods beginning with 'set') may be used as a key and set via this method.

  • setName($name): Set the service name (typically, the function or method name).

  • getName(): Retrieve the service name.

  • setTransport($transport): Set the service transport (currently, only transports supported by Zend_Json_Server_Smd are allowed).

  • getTransport(): Retrieve the current transport.

  • setTarget($target): Set the URL endpoint of the service (typically, this will be the same as the overall SMD to which the service is attached).

  • getTarget(): Get the URL endpoint of the service.

  • setEnvelope($envelopeType): Set the service envelope (currently, only envelopes supported by Zend_Json_Server_Smd are allowed).

  • getEnvelope(): Retrieve the service envelope type.

  • addParam($type, array $options = array(), $order = null): Add a parameter to the service. By default, only the parameter type is necessary. However, you may also specify the order, as well as options such as:

    • name: the parameter name

    • optional: whether or not the parameter is optional

    • default: a default value for the parameter

    • description: text describing the parameter

  • addParams(array $params): Add several parameters at once; each param should be an assoc array containing minimally the key 'type' describing the parameter type, and optionally the key 'order'; any other keys will be passed as $options to addOption().

  • setParams(array $params): Set many parameters at once, overwriting any existing parameters.

  • getParams(): Retrieve all currently set parameters.

  • setReturn($type): Set the return value type of the service.

  • getReturn(): Get the return value type of the service.

  • toArray(): Cast the service to an array.

  • toJson(): Cast the service to a JSON representation.

XML 到 JSON 转换
Zend_Json
Zend Framework手册 中文版
Zend_Layout
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Json
  • 简介
  • 基本用法
  • JSON 对象
  • XML 到 JSON 转换
  • Zend_Json_Server - JSON-RPC server


Zend_Layout - Zend Framework Manual

Zend_Json_Server - JSON-RPC server
Zend Framework Reference
Zend Framework手册 中文版
简介

Zend_Layout

Table of Contents
  • 简介
  • Zend_Layout 快速入门
  • Zend_Layout 配置选项
  • Zend_Layout 高级用法
Zend_Json_Server - JSON-RPC server
Zend Framework Reference
Zend Framework手册 中文版
简介
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


简介 - Zend Framework Manual

Zend_Layout
Zend_Layout
Zend Framework手册 中文版
Zend_Layout 快速入门

简介

Zend_Layout实现经典的两步视图模型，允许开发者把应用程序内容包装在另一个视图，通常是站点的模板。这样的模板被其它项目在术语上称之为layouts。Zend Framework采用这个术语以保持一致性。

Zend_Layout的主要目标如下：

  • 当和Zend Framework MVC 组件一起使用时自动选择和布局的解析（rendering）.

  • 为布局相关的变量和内容提供分离的范围。

  • 允许配置包括布局名称、布局脚本分解（变形）、布局脚本路径。

  • 允许禁止布局、修改布局脚本和其它状态；允许这些在动作控制器和视图脚本里的动作。

  • 象ViewRenderer 一样遵循相同的脚本分解规则（变形），但允许它们也使用不同的规则。

  • 允许在没有 Zend Framework MVC 组件的情况下使用。

Zend_Layout
Zend_Layout
Zend Framework手册 中文版
Zend_Layout 快速入门
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Layout
  • 简介
  • Zend_Layout 快速入门
  • Zend_Layout 配置选项
  • Zend_Layout 高级用法


Zend_Layout 快速入门 - Zend Framework Manual

简介
Zend_Layout
Zend Framework手册 中文版
Zend_Layout 配置选项

Zend_Layout 快速入门

Zend_Layout有两个基本用例：带有Zend Framework MVC和不带。

布局脚本

在两种情况下都需要创建布局脚本。布局脚本简单地使用Zend_View（或者无论哪种你在使用的视图实现）。布局变量用Zend_Layout placeholder 注册，可以通过占位符助手或者通过布局助手从布局对象的对象属性里获取。

如下例：

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

因为Zend_Layout使用Zend_View来解析，你也可以使用任何视图助手注册，并也可以访问任何先前分配的视图变量。特别有用的是各种各样的占位符助手，因为它允许为如 <head>节（section）、导航（navigation）等区域获取内容：

<!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" />
    <?= $this->headTitle() ?>
    <?= $this->headScript() ?>
    <?= $this->headStyle() ?>
</head>
<body>
    <?= $this->render('header.phtml') ?>

    <div id="nav"><?= $this->placeholder('nav') ?></div>

    <div id="content"><?= $this->layout()->content ?></div>

    <?= $this->render('footer.phtml') ?>
</body>
</html>

和Zend Framework MVC一起使用 Zend_Layout

Zend_Controller通过前端控制器插件 和 动作控制器助手 提供了一组丰富的扩展函数。Zend_View 也有助手。当和（Zend Framework）MVC组件一起使用时，Zend_Layout 利用这些多种扩展点。

Zend_Layout::startMvc()创建一个带有任何你提供给它的可选配置的Zend_Layout的实例。接着它注册一个前端控制器插件，一旦派遣循环完成，这个插件就解析带有任何应用程序内容的布局，并且注册一个动作助手允许从动作控制器来访问布局对象。另外，可以任何时候用布局视图助手从视图脚本抓取布局实例。

首先，来看看如何初始化Zend_Layout来和MVC一起使用：

<?php
// In your bootstrap:
Zend_Layout::startMvc();
?>

startMvc() 可以带一个可选的数组或Zend_Config 对象来定制实例；这些选项详见Zend_Layout 配置选项 。

在动作控制器例，你可以把局实例作为一个动作助手来访问：

<?php
class FooController extends Zend_Controller_Action
{
    public function barAction()
    {
        // disable layouts for this action:
        $this->_helper->layout->disableLayout();
    }

    public function bazAction()
    {
        // use different layout script with this action:
        $this->_helper->layout->setLayout('foobaz');
    };
}
?>

在视图脚本里，可以通过layout视图助手来访问布局对象。这个视图助手和其它的有细微的区别：不带参数，返回一个对象而不是一个字符串值。这允许在布局对象里立即调用方法：

<?php $this->layout()->setLayout('foo'); // set alternate layout ?>

在任何时候，通过getMvcInstance() 静态方法获取和MVC一起注册的Zend_Layout的实例：

<?php
// Returns null if startMvc() has not first been called
$layout = Zend_Layout::getMvcInstance();
?>

最后，Zend_Layout 的前端控制器插件有一个除解析布局外的重要特征：它从响应对象获取所有被命名的段（segments）并分配它们为布局变量，分配‘default’段给变量‘content’。这允许访问应用程序内容和在视图脚本里解析。

作为例子，让代码首先点击FooController::indexAction() ，它解析一些内容到缺省的响应段，并接着转发给NavController::menuAction() ，它解析内容给'nav'响应段。最后，转发给CommentController::fetchAction() 并取得一些注释，但是也解析那些给缺省响应段（追加内容给那个段）。视图脚本可以接着分别解析：

<body>
    <!-- renders /nav/menu -->
    <div id="nav"><?= $this->layout()->nav ?></div>

    <!-- renders /foo/index + /comment/fetch -->
    <div id="content"><?= $this->layout()->content ?></div>
</body>

当和动作堆栈 动作助手 和 插件一起协同使用时，这个特性特别有用，通过循环可以设置一个动作堆栈，这样就创建一个部件化的页面。

使用Zend_Layout做为独立的组件

做为独立组件，Zend_Layout不提供和MVC一起使用那样的方便和更多的功能。然而，它仍有两个主要优点：

  • 布局变量范围

  • 从其它视图脚本分离视图脚本布局

当用作独立组件，简单地初始化布局对象，使用不同的访问器来设置状态、设置变量为对象属性和解析布局：

<?php
$layout = new Zend_Layout();

// Set a layout script path:
$layout->setLayoutPath('/path/to/layouts');

// set some variables:
$layout->content = $content;
$layout->nav     = $nav;

// choose a different layout script:
$layout->setLayout('foo');

// render final layout
echo $layout->render();
?>

尝试一下布局

有时候百闻不如一见。下面是一个布局脚本例子来展示它是如何工作的。

< class="inlinemediaobject">

基于所设置的CSS文件，实际元素的顺序可能不同；例如：如果使用绝对位置，导航稍后显示在文档种，但仍在顶部；对于sidebar或header同样适用，然而实际的显示内容的机制保持相同。

简介
Zend_Layout
Zend Framework手册 中文版
Zend_Layout 配置选项
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Layout
  • 简介
  • Zend_Layout 快速入门
  • Zend_Layout 配置选项
  • Zend_Layout 高级用法


Zend_Layout 配置选项 - Zend Framework Manual

Zend_Layout 快速入门
Zend_Layout
Zend Framework手册 中文版
Zend_Layout 高级用法

Zend_Layout 配置选项

Zend_Layout有多种配置选项。这些都可以用调用适当的访问器来设置，传递数组或Zend_Config对象给构造器或startMvc()，传递选项数组给setOptions()，或传递Zend_Config对象给to setConfig()。

  • layout：被使用的布局。使用当前变形器来解析提供给合适的布局视图脚本的名称。缺省地，这个值是'layout'并解析为'layout.phtml'。访问器是setLayout() 和 getLayout()。

  • layoutPath: 布局视图脚本的基本路径。访问器是setLayoutPath() 和 getLayoutPath()。

  • contentKey: 用于缺省内容（和MVC一起使用）的布局变量。缺省值是'content'。访问器是setContentKey() 和 getContentKey()。

  • mvcSuccessfulActionOnly: 当使用MVC，当动作抛出一个异常并且这个标志为true，布局将不被解析（这是为了防止当ErrorHandler plugin 在使用时，布局被双重解析）。缺省地，这个标记是true。访问器是setMvcSuccessfulActionOnly() 和 getMvcSuccessfulActionOnly()。

  • view: 当解析时使用的视图对象。当和MVC一起使用时，如果没有视图对象被显式传递，Zend_Layout 将尝试使用用the ViewRenderer 注册的视图对象。访问器是setView() 和 getView()。

  • helperClass: 当和MVC组件一起使用Zend_Layout 时的动作助手。 缺省是 Zend_Layout_Controller_Action_Helper_Layout。访问器是 setHelperClass() 和 getHelperClass()。

  • pluginClass: 当和MVC组件一起使用Zend_Layout 时的前端控制器插件类。缺省是 Zend_Layout_Controller_Plugin_Layout。访问器是 setPluginClass() 和 getPluginClass()。

  • inflector: 当解析布局名给布局视图脚本路径时的变形器；参见 Zend_Layout 变形器文档有更多细节 。访问器是 setInflector() 和 getInflector()。

Note: 助手类和插件类必须传递给startMvc()
 为了helperClass和pluginClass设置有效，它们必须作为选项传递给startMvc()；如果以后设置，它们就没有影响。

范例

下面的例子假定使用$options数组和$config对象：

<?php
$options = array(
    'layout'     => 'foo',
    'layoutPath' => '/path/to/layouts',
    'contentKey' => 'CONTENT',           // ignored when MVC not used
);
?>
<?php
/**
[layout]
layout = "foo"
layoutPath = "/path/to/layouts"
contentKey = "CONTENT"
*/
$config = new Zend_Config_Ini('/path/to/layout.ini', 'layout');
?>

Example #1 传递选项给构造器或startMvc()

为了配置Zend_Layout实例，构造器和startMvc() 静态方法都可以接受选项数组或带有选项的Zend_Config 对象。

首先，看一下传递数组：

<?php
// Using constructor:
$layout = new Zend_Layout($options);

// Using startMvc():
$layout = Zend_Layout::startMvc($options);
?>

现在使用配置对象：

<?php
$config = new Zend_Config_Ini('/path/to/layout.ini', 'layout');

// Using constructor:
$layout = new Zend_Layout($config);

// Using startMvc():
$layout = Zend_Layout::startMvc($config);
?>

基本上，这是定制Zend_Layout实例的最简单的方法。

Example #2 使用setOption() 和 setConfig()

有时候在Zend_Layout 对象初始化以后才需要配置；setOptions() 和 setConfig()让你快速而起容易地来做：

<?php
// Using an array of options:
$layout->setOptions($options);

// Using a Zend_Config object:
$layout->setConfig($options);
?>

然而要注意特定的选项，如pluginClass 和 helperClass，当用这个方法传递，将没有效果；它们需要传递给构造器或者startMvc() 方法。

Example #3 使用访问器

最后，通过访问器来配置Zend_Layout 实例。所有的访问器实现一个流畅的接口，意味这它们的调用可能被链接：

<?php
$layout->setLayout('foo')
       ->setLayoutPath('/path/to/layouts')
       ->setContentKey('CONTENT');
?>
Zend_Layout 快速入门
Zend_Layout
Zend Framework手册 中文版
Zend_Layout 高级用法
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Layout
  • 简介
  • Zend_Layout 快速入门
  • Zend_Layout 配置选项
  • Zend_Layout 高级用法


Zend_Layout 高级用法 - Zend Framework Manual

Zend_Layout 配置选项
Zend_Layout
Zend Framework手册 中文版
Zend_Ldap

Zend_Layout 高级用法

Zend_Layout 有无数用例提供给愿意修改它以适应不同的视图实现、文件系统布局及更多的高级开发者。

主要的扩展点是：

  • 定制视图对象。 Zend_Layout 允许使用任何实现Zend_View_Interface 的类。

  • 定制前端控制器插件。 Zend_Layout 和在返回响应之前自动解析布局的标准前端控制器插件一起发布。你可以替换你自己的插件。

  • 定制动作助手。 Zend_Layout 和标准动作助手一起发布，因为这个助手对于布局对象自己是一个哑代理（dumb proxy），所以它应该适合大部分的需求。

  • 定制布局脚本路径解析（resolution）。Zend_Layout 允许为布局脚本路径解析使用你自己的 变形器（inflector） ，或者简单地修改附加的变形器来指定你自己的变形规则。

定制视图对象

Zend_Layout 允许任何实现 Zend_View_Interface 的类或者扩展 Zend_View_Abstract 来解析布局脚本。简单地把定制的视图对象当作参数传递给 constructor/startMvc()，或者用setView() 访问器来设置它：

<?php
$view = new My_Custom_View();
$layout->setView($view);
?>

Note: 不是所有的 Zend_View 实现都等同
 虽然Zend_Layout允许使用任何实现Zend_View_Interface的类，如果它们不能使用各种Zend_View助手，也可能遇到问题，特别是布局和占位符助手。这是因为Zend_Layout通过它自己和占位符在可用的对象里设置变量。
如果要使用一个定制的不支持这些助手Zend_View实现，那么需要找到一个办法把布局变量给视图。这可以通过两个办法来实现：扩展Zend_Layout对象和改变render()方法来传递变量给视图；或者，创建自己的插件类，在解析布局前传递它们。
做为替换方案，如果你的视图实现支持任何种类的插件，你可以通过'Zend_Layout'占位符使用占位符助手：

<?php
$placeholders = new Zend_View_Helper_Placeholder();
$layoutVars   = $placeholders->placeholder('Zend_Layout')->getArrayCopy();
?>

定制前端控制器插件

当和MVC组件一起使用，Zend_Layout注册一个前端控制器插件，这个插件把解析布局做为在退出派遣循环之前的最后一个动作。在大多数情况下，缺省的插件适用，但如果你象写你自己的，可以通过传递pluginClass选项给startMvc()方法来指定插件类的名称去加载。

为这个目的所写的任何插件类将需要扩展Zend_Controller_Plugin_Abstract，并应该接受一个布局对象实例做为参数给构造器。另外，你的实现细节取决于你。

被使用缺省插件类是Zend_Layout_Controller_Plugin_Layout。

定制动作助手

当和MVC组件一起使用，Zend_Layout用助手经纪注册一个动作控制器助手。缺省助手，Zend_Layout_Controller_Action_Helper_Layout，扮作一个哑代理给布局对象实例自己，并应该适合大多数用例。

如果你觉得需要写定制的函数，简单地写一个扩展Zend_Controller_Action_Helper_Abstract 的动作助手类并把类名做为helperClass选项传递给startMvc()方法，细节就取决于你了。

定制布局脚本路径解析（Resolution）：使用变形器（Inflector）

为翻译布局名到布局脚本路径，Zend_Layout 用 Zend_Filter_Inflector来建立一个过滤链。缺省地，它遵循'StringToLower'（字符变小写）来使用规则'CamelCaseToDash'（驼峰变短横线）和加后缀'phtml'来转换名字到路径。如下几个例子所示：

  • 'foo' will be transformed to 'foo.phtml'.

  • 'FooBarBaz' will be transformed to 'foo-bar-baz.phtml'.

有三个选项来修改变形：通过Zend_Layout访问器修改变形目标和/或视图后缀，修改变形器规则和与Zend_Layout实例联合变形器目标，或者创建你自己的变形器实例并传递给Zend_Layout::setInflector()。

Example #1 使用Zend_Layout访问器来修改变形器(inflector)

缺省的Zend_Layout变形器对目标和脚本后缀使用静态地址(references)，并拥有访问器来设置这些值。

<?php
// Set the inflector target:
$layout->setInflectorTarget('layouts/:script.:suffix');

// Set the layout view script suffix:
$layout->setViewSuffix('php');
?>

Example #2 Zend_Layout 变形器的直接修改

变形器有目标和一个或多个规则。缺省目标和Zend_Layout一起使用是':script.:suffix'；':script'是被传递的已注册的布局名称，':suffix'是变形器的静态规则。

让我们假设你想用后缀'html'做为布局脚本的文件扩展名，并且想分离混合大小写字和驼峰字为下划线而不是短横线，还不想使用小写字母。另外，你想让它去'layouts'子目录去找脚本。

<?php
$layout->getInflector()->setTarget('layouts/:script.:suffix')
                       ->setStaticRule('suffix', 'html')
                       ->setFilterRule(array('CamelCaseToUnderscore'));
?>

Example #3 定制变形器（inflectors）

在大多数情况下，修改已存在的变形器已经足够。然而，你可能想有一个在多个地方使用的变形器，并带有不同的对象和类型。Zend_Layout支持它。

<?php
$inflector = new Zend_Filter_Inflector('layouts/:script.:suffix');
$inflector->addRules(array(
    ':script' => array('CamelCaseToUnderscore'),
    'suffix'  => 'html'
));
$layout->setInflector($inflector);
?>

Note: 变形（Inflection）可以被禁止
在Zend_Layout对象种用访问器可以禁止和允许变形。这对想指定绝对路径给布局视图脚本来说很有用，或者知道指定布局脚本不需要变形的机制，简单地使用enableInflection() 和 disableInflection() 方法。

Zend_Layout 配置选项
Zend_Layout
Zend Framework手册 中文版
Zend_Ldap
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Layout
  • 简介
  • Zend_Layout 快速入门
  • Zend_Layout 配置选项
  • Zend_Layout 高级用法


Zend_Ldap - Zend Framework Manual

Zend_Layout 高级用法
Zend Framework Reference
Zend Framework手册 中文版
Introduction

Zend_Ldap

Table of Contents
  • Introduction
  • API overview
  • Usage Scenarios
  • Tools
  • Object oriented access to the LDAP tree using Zend_Ldap_Node
  • Getting information from the LDAP server
  • Serializing LDAP data to and from LDIF
Zend_Layout 高级用法
Zend Framework Reference
Zend Framework手册 中文版
Introduction
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


Introduction - Zend Framework Manual

Zend_Ldap
Zend_Ldap
Zend Framework手册 中文版
API overview

Introduction

Zend_Ldap is a class for performing LDAP operations including but not limited to binding, searching and modifying entries in an LDAP directory.

Theory of operation

This component currently consists of the main Zend_Ldap class, that conceptually represents a binding to a single LDAP server and allows for executing operations against a LDAP server such as OpenLDAP or ActiveDirectory (AD) servers. The parameters for binding may be provided explicitly or in the form of an options array. Zend_Ldap_Node provides an object-oriented interface for single LDAP nodes and can be used to form a basis for an active-record-like interface for a LDAP-based domain model.

The component provides several helper classes to perform operations on LDAP entries (Zend_Ldap_Attribute) such as setting and retrieving attributes (date values, passwords, boolean values, ...), to create and modify LDAP filter strings (Zend_Ldap_Filter) and to manipulate LDAP distinguished names (DN) (Zend_Ldap_Dn).

Additionally the component abstracts LDAP schema browsing for OpenLDAP and ActiveDirectoy servers Zend_Ldap_Node_Schema and server information retrieval for OpenLDAP-, ActiveDirectory- and Novell eDirectory servers (Zend_Ldap_Node_RootDse).

Using the Zend_Ldap class depends on the type of LDAP server and is best summarized with some simple examples.

If you are using OpenLDAP, a simple example looks like the following (note that the bindRequiresDn option is important if you are not using AD):

  1. $options = array(
  2.     'host'              => 's0.foo.net',
  3.     'username'          => 'CN=user1,DC=foo,DC=net',
  4.     'password'          => 'pass1',
  5.     'bindRequiresDn'    => true,
  6.     'accountDomainName' => 'foo.net',
  7.     'baseDn'            => 'OU=Sales,DC=foo,DC=net',
  8. );
  9. $ldap = new Zend_Ldap($options);
  10. $acctname = $ldap->getCanonicalAccountName('abaker',
  11.                                            Zend_Ldap::ACCTNAME_FORM_DN);
  12. echo "$acctname\n";

If you are using Microsoft AD a simple example is:

  1. $options = array(
  2.     'host'                   => 'dc1.w.net',
  3.     'useStartTls'            => true,
  4.     'username'               => 'user1@w.net',
  5.     'password'               => 'pass1',
  6.     'accountDomainName'      => 'w.net',
  7.     'accountDomainNameShort' => 'W',
  8.     'baseDn'                 => 'CN=Users,DC=w,DC=net',
  9. );
  10. $ldap = new Zend_Ldap($options);
  11. $acctname = $ldap->getCanonicalAccountName('bcarter',
  12.                                            Zend_Ldap::ACCTNAME_FORM_DN);
  13. echo "$acctname\n";

Note that we use the getCanonicalAccountName() method to retrieve the account DN here only because that is what exercises the most of what little code is currently present in this class.

Automatic Username Canonicalization When Binding

If bind() is called with a non-DN username but bindRequiresDN is TRUE and no username in DN form was supplied as an option, the bind will fail. However, if a username in DN form is supplied in the options array, Zend_Ldap will first bind with that username, retrieve the account DN for the username supplied to bind() and then re-bind with that DN.

This behavior is critical to Zend_Auth_Adapter_Ldap, which passes the username supplied by the user directly to bind().

The following example illustrates how the non-DN username 'abaker' can be used with bind():

  1. $options = array(
  2.         'host'              => 's0.foo.net',
  3.         'username'          => 'CN=user1,DC=foo,DC=net',
  4.         'password'          => 'pass1',
  5.         'bindRequiresDn'    => true,
  6.         'accountDomainName' => 'foo.net',
  7.         'baseDn'            => 'OU=Sales,DC=foo,DC=net',
  8. );
  9. $ldap = new Zend_Ldap($options);
  10. $ldap->bind('abaker', 'moonbike55');
  11. $acctname = $ldap->getCanonicalAccountName('abaker',
  12.                                            Zend_Ldap::ACCTNAME_FORM_DN);
  13. echo "$acctname\n";

The bind() call in this example sees that the username 'abaker' is not in DN form, finds bindRequiresDn is TRUE, uses 'CN=user1,DC=foo,DC=net' and 'pass1' to bind, retrieves the DN for 'abaker', unbinds and then rebinds with the newly discovered 'CN=Alice Baker,OU=Sales,DC=foo,DC=net'.

Account Name Canonicalization

The accountDomainName and accountDomainNameShort options are used for two purposes: (1) they facilitate multi-domain authentication and failover capability, and (2) they are also used to canonicalize usernames. Specifically, names are canonicalized to the form specified by the accountCanonicalForm option. This option may one of the following values:

Options for accountCanonicalForm
Name | Value | Example
ACCTNAME_FORM_DN | 1 | CN=Alice Baker,CN=Users,DC=example,DC=com
ACCTNAME_FORM_USERNAME | 2 | abaker
ACCTNAME_FORM_BACKSLASH | 3 | EXAMPLE\abaker
ACCTNAME_FORM_PRINCIPAL | 4 | abaker@example.com

The default canonicalization depends on what account domain name options were supplied. If accountDomainNameShort was supplied, the default accountCanonicalForm value is ACCTNAME_FORM_BACKSLASH. Otherwise, if accountDomainName was supplied, the default is ACCTNAME_FORM_PRINCIPAL.

Account name canonicalization ensures that the string used to identify an account is consistent regardless of what was supplied to bind(). For example, if the user supplies an account name of abaker@example.com or just abaker and the accountCanonicalForm is set to 3, the resulting canonicalized name would be EXAMPLE\abaker.

Multi-domain Authentication and Failover

The Zend_Ldap component by itself makes no attempt to authenticate with multiple servers. However, Zend_Ldap is specifically designed to handle this scenario gracefully. The required technique is to simply iterate over an array of arrays of serve options and attempt to bind with each server. As described above bind() will automatically canonicalize each name, so it does not matter if the user passes abaker@foo.net or W\bcarter or cdavis - the bind() method will only succeed if the credentials were successfully used in the bind.

Consider the following example that illustrates the technique required to implement multi-domain authentication and failover:

  1. $acctname = 'W\\user2';
  2. $password = 'pass2';
  3.
  4. $multiOptions = array(
  5.     'server1' => array(
  6.         'host'                   => 's0.foo.net',
  7.         'username'               => 'CN=user1,DC=foo,DC=net',
  8.         'password'               => 'pass1',
  9.         'bindRequiresDn'         => true,
  10.         'accountDomainName'      => 'foo.net',
  11.         'accountDomainNameShort' => 'FOO',
  12.         'accountCanonicalForm'   => 4, // ACCT_FORM_PRINCIPAL
  13.         'baseDn'                 => 'OU=Sales,DC=foo,DC=net',
  14.     ),
  15.     'server2' => array(
  16.         'host'                   => 'dc1.w.net',
  17.         'useSsl'                 => true,
  18.         'username'               => 'user1@w.net',
  19.         'password'               => 'pass1',
  20.         'accountDomainName'      => 'w.net',
  21.         'accountDomainNameShort' => 'W',
  22.         'accountCanonicalForm'   => 4, // ACCT_FORM_PRINCIPAL
  23.         'baseDn'                 => 'CN=Users,DC=w,DC=net',
  24.     ),
  25. );
  26.
  27. $ldap = new Zend_Ldap();
  28.
  29. foreach ($multiOptions as $name => $options) {
  30.
  31.     echo "Trying to bind using server options for '$name'\n";
  32.
  33.     $ldap->setOptions($options);
  34.     try {
  35.         $ldap->bind($acctname, $password);
  36.         $acctname = $ldap->getCanonicalAccountName($acctname);
  37.         echo "SUCCESS: authenticated $acctname\n";
  38.         return;
  39.     } catch (Zend_Ldap_Exception $zle) {
  40.         echo '  ' . $zle->getMessage() . "\n";
  41.         if ($zle->getCode() === Zend_Ldap_Exception::LDAP_X_DOMAIN_MISMATCH) {
  42.             continue;
  43.         }
  44.     }
  45. }

If the bind fails for any reason, the next set of server options is tried.

The getCanonicalAccountName() call gets the canonical account name that the application would presumably use to associate data with such as preferences. The accountCanonicalForm = 4 in all server options ensures that the canonical form is consistent regardless of which server was ultimately used.

The special LDAP_X_DOMAIN_MISMATCH exception occurs when an account name with a domain component was supplied (e.g., abaker@foo.net or FOO\abaker and not just abaker) but the domain component did not match either domain in the currently selected server options. This exception indicates that the server is not an authority for the account. In this case, the bind will not be performed, thereby eliminating unnecessary communication with the server. Note that the continue instruction has no effect in this example, but in practice for error handling and debugging purposes, you will probably want to check for LDAP_X_DOMAIN_MISMATCH as well as LDAP_NO_SUCH_OBJECT and LDAP_INVALID_CREDENTIALS.

The above code is very similar to code used within Zend_Auth_Adapter_Ldap. In fact, we recommend that you simply use that authentication adapter for multi-domain + failover LDAP based authentication (or copy the code).

Zend_Ldap
Zend_Ldap
Zend Framework手册 中文版
API overview
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Ldap
  • Introduction
  • API overview
  • Usage Scenarios
  • Tools
  • Object oriented access to the LDAP tree using Zend_Ldap_Node
  • Getting information from the LDAP server
  • Serializing LDAP data to and from LDIF


API overview - Zend Framework Manual

Introduction
Zend_Ldap
Zend Framework手册 中文版
Usage Scenarios

API overview

Configuration / options

The Zend_Ldap component accepts an array of options either supplied to the constructor or through the setOptions() method. The permitted options are as follows:

Zend_Ldap Options
Name | Description
host | The default hostname of LDAP server if not supplied to connect() (also may be used when trying to canonicalize usernames in bind()).
port | Default port of LDAP server if not supplied to connect().
useStartTls | Whether or not the LDAP client should use TLS (aka SSLv2) encrypted transport. A value of TRUE is strongly favored in production environments to prevent passwords from be transmitted in clear text. The default value is FALSE, as servers frequently require that a certificate be installed separately after installation. The useSsl and useStartTls options are mutually exclusive. The useStartTls option should be favored over useSsl but not all servers support this newer mechanism.
useSsl | Whether or not the LDAP client should use SSL encrypted transport. The useSsl and useStartTls options are mutually exclusive.
username | The default credentials username. Some servers require that this be in DN form. This must be given in DN form if the LDAP server requires a DN to bind and binding should be possible with simple usernames.
password | The default credentials password (used only with username above).
bindRequiresDn | If TRUE, this instructs Zend_Ldap to retrieve the DN for the account used to bind if the username is not already in DN form. The default value is FALSE.
baseDn | The default base DN used for searching (e.g., for accounts). This option is required for most account related operations and should indicate the DN under which accounts are located.
accountCanonicalForm | A small integer indicating the form to which account names should be canonicalized. See the Account Name Canonicalization section below.
accountDomainName | The FQDN domain for which the target LDAP server is an authority (e.g., example.com).
accountDomainNameShort | The 'short' domain for which the target LDAP server is an authority. This is usually used to specify the NetBIOS domain name for Windows networks but may also be used by non-AD servers.
accountFilterFormat | The LDAP search filter used to search for accounts. This string is a » sprintf() style expression that must contain one '%s' to accommodate the username. The default value is '(&(objectClass=user)(sAMAccountName=%s))' unless bindRequiresDn is set to TRUE, in which case the default is '(&(objectClass=posixAccount)(uid=%s))'. Users of custom schemas may need to change this option.
allowEmptyPassword | Some LDAP servers can be configured to accept an empty string password as an anonymous bind. This behavior is almost always undesirable. For this reason, empty passwords are explicitly disallowed. Set this value to TRUE to allow an empty string password to be submitted during the bind.
optReferrals | If set to TRUE, this option indicates to the LDAP client that referrals should be followed. The default value is FALSE.
tryUsernameSplit | If set to FALSE, this option indicates that the given username should not be split at the first @ or \ character to separate the username from the domain during the binding-procedure. This allows the user to use usernames that contain an @ or \ character that do not inherit some domain-information, e.g. using email-addresses for binding. The default value is TRUE.

API Reference

Note: Method names in italics are static methods.

Zend_Ldap

Zend_Ldap is the base interface into a LDAP server. It provides connection and binding methods as well as methods to operate on the LDAP tree.

Zend_Ldap API
Method | Description
string filterEscape(string $str) | Escapes a value to be used in a LDAP filter according to RFC 2254. This method is deprecated, please use Zend_Ldap_Filter_Abstract::escapeValue() instead.
boolean explodeDn($dn, array &$keys = null, array &$vals = null) | Checks if a given DN $dn is malformed. If $keys or $keys and $vals are given, these arrays will be filled with the appropriate DN keys and values. This method is deprecated, please use Zend_Ldap_Dn::checkDn() instead.
__construct($options) | Constructor. The $options parameter is optional and can be set to an array or a Zend_Config instance. If no options are provided at instantiation, the connection parameters must be passed to the instance using Zend_Ldap::setOptions(). The allowed options are specified in Zend_Ldap Options
resource getResource() | Returns the raw LDAP extension (ext/ldap) resource.
integer getLastErrorCode() | Returns the LDAP error number of the last LDAP command.
string getLastError(integer &$errorCode, array &$errorMessages) | Returns the LDAP error message of the last LDAP command. The optional $errorCode parameter is set to the LDAP error number when given. The optional $errorMessages array will be filled with the raw error messages when given. The various LDAP error retrieval functions can return different things, so they are all collected if $errorMessages is given.
Zend_Ldap setOptions($options) | Sets the LDAP connection and binding parameters. $options can be an array or an instance of Zend_Config. The allowed options are specified in Zend_Ldap Options
array getOptions() | Returns the current connection and binding parameters.
string getBaseDn() | Returns the base DN this LDAP connection is bound to.
string getCanonicalAccountName(string $acctname, integer $form) | Returns the canonical account name of the given account name $acctname. $form specifies the format into which the account name is canonicalized. See Account Name Canonicalization for more details.
Zend_Ldap disconnect() | Disconnects the Zend_Ldap instance from the LDAP server.
Zend_Ldap connect(string $host, integer $port, boolean $useSsl, boolean $useStartTls) | Connects the Zend_Ldap instance to the given LDAP server. All parameters are optional and will be taken from the LDAP connection and binding parameters passed to the instance via the construtor or via Zend_Ldap::setOptions() when set to NULL.
Zend_Ldap bind(string $username, string $password) | Authenticates $username with $password at the LDAP server. If both paramaters are omitted the binding will be carried out with the credentials given in the connection and binding parameters. If no credentials are given in the connection and binding parameters an anonymous bind will be performed. Note that this requires anonymous binds to be allowed on the LDAP server. An empty string '' can be passed as $password together with a username if, and only if, allowEmptyPassword is set to TRUE in the connection and binding parameters.
Zend_Ldap_Collection search(string|Zend_Ldap_Filter_Abstract $filter, string|Zend_Ldap_Dn $basedn, integer $scope, array $attributes, string $sort, string $collectionClass) Searches the LDAP tree with the given $filter and the given search parameters.
string|Zend_Ldap_Filter_Abstract $filter

The filter string to be used in the search, e.g. (objectClass=posixAccount).

string|Zend_Ldap_Dn $basedn

The search base for the search. If omitted or NULL, the baseDn from the connection and binding parameters is used.

integer $scope

The search scope. Zend_Ldap::SEARCH_SCOPE_SUB searches the complete subtree including the $baseDn node. Zend_Ldap::SEARCH_SCOPE_ONE restricts search to one level below $baseDn. Zend_Ldap::SEARCH_SCOPE_BASE restricts search to the $baseDn itself; this can be used to efficiently retrieve a single entry by its DN. The default value is Zend_Ldap::SEARCH_SCOPE_SUB.

array $attributes

Specifies the attributes contained in the returned entries. To include all possible attributes (ACL restrictions can disallow certain attribute to be retrieved by a given user) pass either an empty array array() or array('*') to the method. On some LDAP servers you can retrieve special internal attributes by passing array('*', '+') to the method.

string $sort

If given the result collection will be sorted after the attribute $sort. Results can only be sorted after one single attribute as this parameter uses the ext/ldap function ldap_sort().

string $collectionClass

If given the result will be wrapped in an object of type $collectionClass. By default an object of type Zend_Ldap_Collection will be returned. The custom class must extend Zend_Ldap_Collection and will be passed a Zend_Ldap_Collection_Iterator_Default on instantiation.

integer count(string|Zend_Ldap_Filter_Abstract $filter, string|Zend_Ldap_Dn $basedn, integer $scope) | Counts the elements returned by the given search parameters. See Zend_Ldap::search() for a detailed description of the method parameters.
integer countChildren(string|Zend_Ldap_Dn $dn) | Counts the direct descendants (children) of the entry identified by the given $dn.
boolean exists(string|Zend_Ldap_Dn $dn) | Checks whether the entry identified by the given $dn exists.
array searchEntries(string|Zend_Ldap_Filter_Abstract $filter, string|Zend_Ldap_Dn $basedn, integer $scope, array $attributes, string $sort) | Performs a search operation and returns the result as an PHP array. This is essentially the same method as Zend_Ldap::search() except for the return type. See Zend_Ldap::search() for a detailed description of the method parameters.
array getEntry(string|Zend_Ldap_Dn $dn, array $attributes, boolean $throwOnNotFound) | Retrieves the LDAP entry identified by $dn with the attributes specified in $attributes. If $attributes is ommitted, all attributes ( array()) are included in the result. $throwOnNotFound is FALSE by default, so the method will return NULL if the specified entry cannot be found. If set to TRUE, a Zend_Ldap_Exception will be thrown instead.
void prepareLdapEntryArray(array &$entry) | Prepare an array for the use in LDAP modification operations. This method does not need to be called by the end-user as it's implicitly called on every data modification method.
Zend_Ldap add(string|Zend_Ldap_Dn $dn, array $entry) | Adds the entry identified by $dn with its attributes $entry to the LDAP tree. Throws a Zend_Ldap_Exception if the entry could not be added.
Zend_Ldap update(string|Zend_Ldap_Dn $dn, array $entry) | Updates the entry identified by $dn with its attributes $entry to the LDAP tree. Throws a Zend_Ldap_Exception if the entry could not be modified.
Zend_Ldap save(string|Zend_Ldap_Dn $dn, array $entry) | Saves the entry identified by $dn with its attributes $entry to the LDAP tree. Throws a Zend_Ldap_Exception if the entry could not be saved. This method decides by querying the LDAP tree if the entry will be added or updated.
Zend_Ldap delete(string|Zend_Ldap_Dn $dn, boolean $recursively) | Deletes the entry identified by $dn from the LDAP tree. Throws a Zend_Ldap_Exception if the entry could not be deleted. $recursively is FALSE by default. If set to TRUE the deletion will be carried out recursively and will effectively delete a complete subtree. Deletion will fail if $recursively is FALSE and the entry $dn is not a leaf entry.
Zend_Ldap moveToSubtree(string|Zend_Ldap_Dn $from, string|Zend_Ldap_Dn $to, boolean $recursively, boolean $alwaysEmulate) Moves the entry identified by $from to a location below $to keeping its RDN unchanged. $recursively specifies if the operation will be carried out recursively (FALSE by default) so that the entry $from and all its descendants will be moved. Moving will fail if $recursively is FALSE and the entry $from is not a leaf entry. $alwaysEmulate controls whether the ext/ldap function ldap_rename() should be used if available. This can only work for leaf entries and for servers and for ext/ldap supporting this function. Set to TRUE to always use an emulated rename operation.

Note: All move-operations are carried out by copying and then deleting the corresponding entries in the LDAP tree. These operations are not atomic so that failures during the operation will result in an inconsistent state on the LDAP server. The same is true for all recursive operations. They also are by no means atomic. Please keep this in mind.

Zend_Ldap move(string|Zend_Ldap_Dn $from, string|Zend_Ldap_Dn $to, boolean $recursively, boolean $alwaysEmulate) | This is an alias for Zend_Ldap::rename().
Zend_Ldap rename(string|Zend_Ldap_Dn $from, string|Zend_Ldap_Dn $to, boolean $recursively, boolean $alwaysEmulate) | Renames the entry identified by $from to $to. $recursively specifies if the operation will be carried out recursively (FALSE by default) so that the entry $from and all its descendants will be moved. Moving will fail if $recursively is FALSE and the entry $from is not a leaf entry. $alwaysEmulate controls whether the ext/ldap function ldap_rename() should be used if available. This can only work for leaf entries and for servers and for ext/ldap supporting this function. Set to TRUE to always use an emulated rename operation.
Zend_Ldap copyToSubtree(string|Zend_Ldap_Dn $from, string|Zend_Ldap_Dn $to, boolean $recursively) | Copies the entry identified by $from to a location below $to keeping its RDN unchanged. $recursively specifies if the operation will be carried out recursively (FALSE by default) so that the entry $from and all its descendants will be copied. Copying will fail if $recursively is FALSE and the entry $from is not a leaf entry.
Zend_Ldap copy(string|Zend_Ldap_Dn $from, string|Zend_Ldap_Dn $to, boolean $recursively) | Copies the entry identified by $from to $to. $recursively specifies if the operation will be carried out recursively (FALSE by default) so that the entry $from and all its descendants will be copied. Copying will fail if $recursively is FALSE and the entry $from is not a leaf entry.
Zend_Ldap_Node getNode(string|Zend_Ldap_Dn $dn) | Returns the entry $dn wrapped in a Zend_Ldap_Node.
Zend_Ldap_Node getBaseNode() | Returns the entry for the base DN $baseDn wrapped in a Zend_Ldap_Node.
Zend_Ldap_Node_RootDse getRootDse() | Returns the RootDSE for the current server.
Zend_Ldap_Node_Schema getSchema() | Returns the LDAP schema for the current server.

Zend_Ldap_Collection

Zend_Ldap_Collection implements Iterator to allow for item traversal using foreach() and Countable to be able to respond to count(). With its protected _createEntry() method it provides a simple extension point for developers needing custom result objects.

Zend_Ldap_Collection API
Method | Description
__construct(Zend_Ldap_Collection_Iterator_Interface $iterator) | Constructor. The constrcutor must be provided by a Zend_Ldap_Collection_Iterator_Interface which does the real result iteration. Zend_Ldap_Collection_Iterator_Default is the default implementation for iterating ext/ldap results.
boolean close() | Closes the internal iterator. This is also called in the destructor.
array toArray() | Returns all entries as an array.
array getFirst() | Returns the first entry in the collection or NULL if the collection is empty.

Zend_Ldap_Attribute

Zend_Ldap_Attribute is a helper class providing only static methods to manipulate arrays suitable to the structure used in Zend_Ldap data modification methods and to the data format required by the LDAP server. PHP data types are converted the following way:

string

No conversion will be done.

integer and float

The value will be converted to a string.

boolean

TRUE will be converted to 'TRUE' and FALSE to 'FALSE'

object and array

The value will be converted to a string by using serialize().

resource

If a stream resource is given, the data will be fetched by calling stream_get_contents().

others

All other data types (namely non-stream resources) will be ommitted.

On reading attribute values the following conversion will take place:

'TRUE'

Converted to TRUE.

'FALSE'

Converted to FALSE.

others

All other strings won't be automatically converted and are passed as they are.

Zend_Ldap_Attribute API
Method | Description
void setAttribute(array &$data, string $attribName, mixed $value, boolean $append) | Sets the attribute $attribName in $data to the value $value. If $append is TRUE (FALSE by default) $value will be appended to the attribute. $value can be a scalar value or an array of scalar values. Conversion will take place.
array|mixed getAttribute(array $data, string $attribName, integer|null $index) | Returns the attribute $attribName from $data. If $index is NULL (default) an array will be returned containing all the values for the given attribute. An empty array will be returned if the attribute does not exist in the given array. If an integer index is specified the corresponding value at the given index will be returned. If the index is out of bounds, NULL will be returned. Conversion will take place.
boolean attributeHasValue(array &$data, string $attribName, mixed|array $value) | Checks if the attribute $attribName in $data has the value(s) given in $value. The method returns TRUE only if all values in $value are present in the attribute. Comparison is done strictly (respecting the data type).
void removeDuplicatesFromAttribute(array &$data, string $attribName) | Removes all duplicates from the attribute $attribName in $data.
void removeFromAttribute(array &$data, string $attribName, mixed|array $value) | Removes the value(s) given in $value from the attribute $attribName in $data.
string|null convertToLdapValue(mixed $value) | Converts a PHP data type into its LDAP representation. See introduction for details.
mixed convertFromLdapValue(string $value) | Converts an LDAP value into its PHP data type. See introduction for details.
string|null convertToLdapDateTimeValue(integer $value, boolean $utc) | Converts a timestamp into its LDAP date/time representation. If $utc is TRUE (FALSE by default) the resulting LDAP date/time string will be in UTC, otherwise a local date/time string will be returned.
integer|null convertFromLdapDateTimeValue(string $value) | Converts LDAP date/time representation into a timestamp. The method returns NULL if $value can not be converted back into a PHP timestamp.
void setPassword(array &$data, string $password, string $hashType, string $attribName) | Sets a LDAP password for the attribute $attribName in $data. $attribName defaults to 'userPassword' which is the standard password attribute. The password hash can be specified with $hashType. The default value here is Zend_Ldap_Attribute::PASSWORD_HASH_MD5 with Zend_Ldap_Attribute::PASSWORD_HASH_SHA as the other possibilty.
string createPassword(string $password, string $hashType) | Creates a LDAP password. The password hash can be specified with $hashType. The default value here is Zend_Ldap_Attribute::PASSWORD_HASH_MD5 with Zend_Ldap_Attribute::PASSWORD_HASH_SHA as the other possibilty.
void setDateTimeAttribute(array &$data, string $attribName, integer|array $value, boolean $utc, boolean $append) | Sets the attribute $attribName in $data to the date/time value $value. If $append is TRUE (FALSE by default) $value will be appended to the attribute. $value can be an integer value or an array of integers. Date-time-conversion according to Zend_Ldap_Attribute::convertToLdapDateTimeValue() will take place.
array|integer getDateTimeAttribute(array $data, string $attribName, integer|null $index) | Returns the date/time attribute $attribName from $data. If $index is NULL (default) an array will be returned containing all the date/time values for the given attribute. An empty array will be returned if the attribute does not exist in the given array. If an integer index is specified the corresponding date/time value at the given index will be returned. If the index is out of bounds, NULL will be returned. Date-time-conversion according to Zend_Ldap_Attribute::convertFromLdapDateTimeValue() will take place.

Zend_Ldap_Dn

Zend_Ldap_Dn provides an object-oriented interface to manipulating LDAP distinguished names (DN). The parameter $caseFold that is used in several methods determines the way DN attributes are handled regarding their case. Allowed values for this paraneter are:

Zend_Ldap_Dn::ATTR_CASEFOLD_NONE

No case-folding will be done.

Zend_Ldap_Dn::ATTR_CASEFOLD_UPPER

All attributes will be converted to upper-case.

Zend_Ldap_Dn::ATTR_CASEFOLD_LOWER

All attributes will be converted to lower-case.

The default case-folding is Zend_Ldap_Dn::ATTR_CASEFOLD_NONE and can be set with Zend_Ldap_Dn::setDefaultCaseFold(). Each instance of Zend_Ldap_Dn can have its own case-folding-setting. If the $caseFold parameter is ommitted in method-calls it defaults to the instance's case-folding setting.

The class implements ArrayAccess to allow indexer-access to the different parts of the DN. The ArrayAccess-methods proxy to Zend_Ldap_Dn::get($offset, 1, null) for offsetGet(integer $offset), to Zend_Ldap_Dn::set($offset, $value) for offsetSet() and to Zend_Ldap_Dn::remove($offset, 1) for offsetUnset(). offsetExists() simply checks if the index is within the bounds.

Zend_Ldap_Dn API
Method | Description
Zend_Ldap_Dn factory(string|array $dn, string|null $caseFold) | Creates a Zend_Ldap_Dn instance from an array or a string. The array must conform to the array structure detailed under Zend_Ldap_Dn::implodeDn().
Zend_Ldap_Dn fromString(string $dn, string|null $caseFold) | Creates a Zend_Ldap_Dn instance from a string.
Zend_Ldap_Dn fromArray(array $dn, string|null $caseFold) | Creates a Zend_Ldap_Dn instance from an array. The array must conform to the array structure detailed under Zend_Ldap_Dn::implodeDn().
array getRdn(string|null $caseFold) | Gets the RDN of the current DN. The return value is an array with the RDN attribute names its keys and the RDN attribute values.
string getRdnString(string|null $caseFold) | Gets the RDN of the current DN. The return value is a string.
Zend_Ldap_Dn getParentDn(integer $levelUp) | Gets the DN of the current DN's ancestor $levelUp levels up the tree. $levelUp defaults to 1.
array get(integer $index, integer $length, string|null $caseFold) | Returns a slice of the current DN determined by $index and $length. $index starts with 0 on the DN part from the left.
Zend_Ldap_Dn set(integer $index, array $value) | Replaces a DN part in the current DN. This operation manipulates the current instance.
Zend_Ldap_Dn remove(integer $index, integer $length) | Removes a DN part from the current DN. This operation manipulates the current instance. $length defaults to 1
Zend_Ldap_Dn append(array $value) | Appends a DN part to the current DN. This operation manipulates the current instance.
Zend_Ldap_Dn prepend(array $value) | Prepends a DN part to the current DN. This operation manipulates the current instance.
Zend_Ldap_Dn insert(integer $index, array $value) | Inserts a DN part after the index $index to the current DN. This operation manipulates the current instance.
void setCaseFold(string|null $caseFold) | Sets the case-folding option to the current DN instance. If $caseFold is NULL the default case-folding setting (Zend_Ldap_Dn::ATTR_CASEFOLD_NONE by default or set via Zend_Ldap_Dn::setDefaultCaseFold() will be set for the current instance.
string toString(string|null $caseFold) | Returns DN as a string.
array toArray(string|null $caseFold) | Returns DN as an array.
string __toString() | Returns DN as a string - proxies to Zend_Ldap_Dn::toString(null).
void setDefaultCaseFold(string $caseFold) | Sets the default case-folding option used by all instances on creation by default. Already existing instances are not affected by this setting.
array escapeValue(string|array $values) | Escapes a DN value according to RFC 2253.
array unescapeValue(string|array $values) | Undoes the conversion done by Zend_Ldap_Dn::escapeValue().
array explodeDn(string $dn, array &$keys, array &$vals, string|null $caseFold) Explodes the DN $dn into an array containing all parts of the given DN. $keys optinally receive DN keys (e.g. CN, OU, DC, ...). $vals optionally receive DN values. The resulting array will be of type
  1. array(
  2. array("cn" => "name1", "uid" => "user"),
  3. array("cn" => "name2"),
  4. array("dc" => "example"),
  5. array("dc" => "org")
  6. )
for a DN of cn=name1+uid=user,cn=name2,dc=example,dc=org.
boolean checkDn(string $dn, array &$keys, array &$vals, string|null $caseFold) | Checks if a given DN $dn is malformed. If $keys or $keys and $vals are given, these arrays will be filled with the appropriate DN keys and values.
string implodeRdn(array $part, string|null $caseFold) | Returns a DN part in the form $attribute=$value
string implodeDn(array $dnArray, string|null $caseFold, string $separator) Implodes an array in the form delivered by Zend_Ldap_Dn::explodeDn() to a DN string. $separator defaults to ',' but some LDAP servers also understand ';'. $dnArray must of type
  1. array(
  2. array("cn" => "name1", "uid" => "user"),
  3. array("cn" => "name2"),
  4. array("dc" => "example"),
  5. array("dc" => "org")
  6. )
boolean isChildOf(string|Zend_Ldap_Dn $childDn, string|Zend_Ldap_Dn $parentDn) | Checks if given $childDn is beneath $parentDn subtree.

Zend_Ldap_Filter

Zend_Ldap_Filter API
Method | Description
Zend_Ldap_Filter equals(string $attr, string $value) | Creates an 'equals' filter: (attr=value).
Zend_Ldap_Filter begins(string $attr, string $value) | Creates an 'begins with' filter: (attr=value*).
Zend_Ldap_Filter ends(string $attr, string $value) | Creates an 'ends with' filter: (attr=*value).
Zend_Ldap_Filter contains(string $attr, string $value) | Creates an 'contains' filter: (attr=*value*).
Zend_Ldap_Filter greater(string $attr, string $value) | Creates an 'greater' filter: (attr>value).
Zend_Ldap_Filter greaterOrEqual(string $attr, string $value) | Creates an 'greater or equal' filter: (attr>=value).
Zend_Ldap_Filter less(string $attr, string $value) | Creates an 'less' filter: (attr<value).
Zend_Ldap_Filter lessOrEqual(string $attr, string $value) | Creates an 'less or equal' filter: (attr<=value).
Zend_Ldap_Filter approx(string $attr, string $value) | Creates an 'approx' filter: (attr~=value).
Zend_Ldap_Filter any(string $attr) | Creates an 'any' filter: (attr=*).
Zend_Ldap_Filter string(string $filter) | Creates a simple custom string filter. The user is responsible for all value-escaping as the filter is used as is.
Zend_Ldap_Filter mask(string $mask, string $value,...) | Creates a filter from a string mask. All $value parameters will be escaped and substituted into $mask by using » sprintf()
Zend_Ldap_Filter andFilter(Zend_Ldap_Filter_Abstract $filter,...) | Creates an 'and' filter from all arguments given.
Zend_Ldap_Filter orFilter(Zend_Ldap_Filter_Abstract $filter,...) | Creates an 'or' filter from all arguments given.
__construct(string $attr, string $value, string $filtertype, string|null $prepend, string|null $append) | Constructor. Creates an arbitrary filter according to the parameters supplied. The resulting filter will be a concatenation $attr . $filtertype . $prepend . $value . $append. Normally this constructor is not needed as all filters can be created by using the appropriate factory methods.
string toString() | Returns a string representation of the filter.
string __toString() | Returns a string representation of the filter. Proxies to Zend_Ldap_Filter::toString().
Zend_Ldap_Filter_Abstract negate() | Negates the current filter.
Zend_Ldap_Filter_Abstract addAnd(Zend_Ldap_Filter_Abstract $filter,...) | Creates an 'and' filter from the current filter and all filters passed in as the arguments.
Zend_Ldap_Filter_Abstract addOr(Zend_Ldap_Filter_Abstract $filter,...) | Creates an 'or' filter from the current filter and all filters passed in as the arguments.
string|array escapeValue(string|array $values) | Escapes the given $values according to RFC 2254 so that they can be safely used in LDAP filters. If a single string is given, a string is returned - otherwise an array is returned. Any control characters with an ASCII code < 32 as well as the characters with special meaning in LDAP filters "*", "(", ")", and "\" (the backslash) are converted into the representation of a backslash followed by two hex digits representing the hexadecimal value of the character.
string|array unescapeValue(string|array $values) | Undoes the conversion done by Zend_Ldap_Filter::escapeValue(). Converts any sequences of a backslash followed by two hex digits into the corresponding character.

Zend_Ldap_Node

Zend_Ldap_Node includes the magic property accessors __set(), __get(), __unset() and __isset() to access the attributes by their name. They proxy to Zend_Ldap_Node::setAttribute(), Zend_Ldap_Node::getAttribute(), Zend_Ldap_Node::deleteAttribute() and Zend_Ldap_Node::existsAttribute() respectively. Furthermore the class implements ArrayAccess for array-style-access to the attributes. Zend_Ldap_Node also implements Iterator and RecursiveIterato to allow for recursive tree-traversal.

Zend_Ldap_Node API
Method | Description
Zend_Ldap getLdap() | Returns the current LDAP connection. Throws Zend_Ldap_Exception if current node is in detached mode (not connected to a Zend_Ldap instance).
Zend_Ldap_Node attachLdap(Zend_Ldap $ldap) | Attach the current node to the $ldap Zend_Ldap instance. Throws Zend_Ldap_Exception if $ldap is not responsible for the current node (node is not a child of the $ldap base DN).
Zend_Ldap_Node detachLdap() | Detach node from LDAP connection.
boolean isAttached() | Checks if the current node is attached to a LDAP connection.
Zend_Ldap_Node create(string|array|Zend_Ldap_Dn $dn, array $objectClass) | Factory method to create a new detached Zend_Ldap_Node for a given DN. Creates a new Zend_Ldap_Node with the DN $dn and the object-classes $objectClass.
Zend_Ldap_Node fromLdap(string|array|Zend_Ldap_Dn $dn, Zend_Ldap $ldap) | Factory method to create an attached Zend_Ldap_Node for a given DN. Loads an existing Zend_Ldap_Node with the DN $dn from the LDAP connection $ldap.
Zend_Ldap_Node fromArray((array $data, boolean $fromDataSource) | Factory method to create a detached Zend_Ldap_Node from array data $data. If $fromDataSource is TRUE (FALSE by default), the data is treated as beeing present in a LDAP tree.
boolean isNew() | Tells if the node is consiedered as new (not present on the server). Please note, that this doesn't tell if the node is really present on the server. Use Zend_Ldap_Node::exists() to see if a node is already there.
boolean willBeDeleted() | Tells if this node is going to be deleted once Zend_Ldap_Node::update() is called.
Zend_Ldap_Node delete() | Marks this node as to be deleted. Node will be deleted on calling Zend_Ldap_Node::update() if Zend_Ldap_Node::willBeDeleted() is TRUE.
boolean willBeMoved() | Tells if this node is going to be moved once Zend_Ldap_Node::update() is called.
Zend_Ldap_Node update(Zend_Ldap $ldap) | Sends all pending changes to the LDAP server. If $ldap is omitted the current LDAP connection is used. If the current node is detached from a LDAP connection a Zend_Ldap_Exception will be thrown. If $ldap is provided the current node will be attached to the given LDAP connection.
Zend_Ldap_Dn getCurrentDn() | Gets the current DN of the current node as a Zend_Ldap_Dn. This does not reflect possible rename-operations.
Zend_Ldap_Dn getDn() | Gets the original DN of the current node as a Zend_Ldap_Dn. This reflects possible rename-operations.
string getDnString(string $caseFold) | Gets the original DN of the current node as a string. This reflects possible rename-operations.
array getDnArray(string $caseFold) | Gets the original DN of the current node as an array. This reflects possible rename-operations.
string getRdnString(string $caseFold) | Gets the RDN of the current node as a string. This reflects possible rename-operations.
array getRdnArray(string $caseFold) | Gets the RDN of the current node as an array. This reflects possible rename-operations.
Zend_Ldap_Node setDn(Zend_Ldap_Dn|string|array $newDn) | Sets the new DN for this node effectively moving the node once Zend_Ldap_Node::update() is called.
Zend_Ldap_Node move(Zend_Ldap_Dn|string|array $newDn) | This is an alias for Zend_Ldap_Node::setDn().
Zend_Ldap_Node rename(Zend_Ldap_Dn|string|array $newDn) | This is an alias for Zend_Ldap_Node::setDn().
array getObjectClass() | Returns the objectClass of the node.
Zend_Ldap_Node setObjectClass(array|string $value) | Sets the objectClass attribute.
Zend_Ldap_Node appendObjectClass(array|string $value) | Appends to the objectClass attribute.
string toLdif(array $options) | Returns a LDIF representation of the current node. $options will be passed to the Zend_Ldap_Ldif_Encoder.
array getChangedData() | Gets changed node data. The array contains all changed attributes. This format can be used in Zend_Ldap::add() and Zend_Ldap::update().
array getChanges() | Returns all changes made.
string toString() | Returns the DN of the current node - proxies to Zend_Ldap_Dn::getDnString().
string __toString() | Casts to string representation - proxies to Zend_Ldap_Dn::toString().
array toArray(boolean $includeSystemAttributes) | Returns an array representation of the current node. If $includeSystemAttributes is FALSE (defaults to TRUE) the system specific attributes are stripped from the array. Unlike Zend_Ldap_Node::getAttributes() the resulting array contains the DN with key 'dn'.
string toJson(boolean $includeSystemAttributes) | Returns a JSON representation of the current node using Zend_Ldap_Node::toArray().
array getData(boolean $includeSystemAttributes) | Returns the node's attributes. The array contains all attributes in its internal format (no conversion).
boolean existsAttribute(string $name, boolean $emptyExists) | Checks whether a given attribute exists. If $emptyExists is FALSE empty attributes (containing only array()) are treated as non-existent returning FALSE. If $emptyExists is TRUE empty attributes are treated as existent returning TRUE. In this case the method returns FALSE only if the attribute name is missing in the key-collection.
boolean attributeHasValue(string $name, mixed|array $value) | Checks if the given value(s) exist in the attribute. The method returns TRUE only if all values in $value are present in the attribute. Comparison is done strictly (respecting the data type).
integer count() | Returns the number of attributes in the node. Implements Countable.
mixed getAttribute(string $name, integer|null $index) | Gets a LDAP attribute. Data conversion is applied using Zend_Ldap_Attribute::getAttribute().
array getAttributes(boolean $includeSystemAttributes) | Gets all attributes of node. If $includeSystemAttributes is FALSE (defaults to TRUE) the system specific attributes are stripped from the array.
Zend_Ldap_Node setAttribute(string $name, mixed $value) | Sets a LDAP attribute. Data conversion is applied using Zend_Ldap_Attribute::setAttribute().
Zend_Ldap_Node appendToAttribute(string $name, mixed $value) | Appends to a LDAP attribute. Data conversion is applied using Zend_Ldap_Attribute::setAttribute().
array|integer getDateTimeAttribute(string $name, integer|null $index) | Gets a LDAP date/time attribute. Data conversion is applied using Zend_Ldap_Attribute::getDateTimeAttribute().
Zend_Ldap_Node setDateTimeAttribute(string $name, integer|array $value, boolean $utc) | Sets a LDAP date/time attribute. Data conversion is applied using Zend_Ldap_Attribute::setDateTimeAttribute().
Zend_Ldap_Node appendToDateTimeAttribute(string $name, integer|array $value, boolean $utc) | Appends to a LDAP date/time attribute. Data conversion is applied using Zend_Ldap_Attribute::setDateTimeAttribute().
Zend_Ldap_Node setPasswordAttribute(string $password, string $hashType, string $attribName) | Sets a LDAP password on $attribName (defaults to 'userPassword') to $password with the hash type $hashType (defaults to Zend_Ldap_Attribute::PASSWORD_HASH_MD5).
Zend_Ldap_Node deleteAttribute(string $name) | Deletes a LDAP attribute.
void removeDuplicatesFromAttribute(string $name) | Removes duplicate values from a LDAP attribute.
void removeFromAttribute(string $attribName, mixed|array $value) | Removes the given values from a LDAP attribute.
boolean exists(Zend_Ldap $ldap) | Checks if the current node exists on the given LDAP server (current server is used if NULL is passed).
Zend_Ldap_Node reload(Zend_Ldap $ldap) | Reloads the current node's attributes from the given LDAP server (current server is used if NULL is passed).
Zend_Ldap_Node_Collection searchSubtree(string|Zend_Ldap_Filter_Abstract $filter, integer $scope, string $sort) | Searches the nodes's subtree with the given $filter and the given search parameters. See Zend_Ldap::search() for details on the parameters $scope and $sort.
integer countSubtree(string|Zend_Ldap_Filter_Abstract $filter, integer $scope) | Count the nodes's subtree items matching the given $filter and the given search scope. See Zend_Ldap::search() for details on the $scope parameter.
integer countChildren() | Count the nodes's children.
Zend_Ldap_Node_Collection searchChildren(string|Zend_Ldap_Filter_Abstract $filter, string $sort) | Searches the nodes's children matching the given $filter. See Zend_Ldap::search() for details on the $sort parameter.
boolean hasChildren() | Returns whether the current node has children.
Zend_Ldap_Node_ChildrenIterator getChildren() | Returns all children of the current node.
Zend_Ldap_Node getParent(Zend_Ldap $ldap) | Returns the parent of the current node using the LDAP connection $ldap (uses the current LDAP connection if omitted).

Zend_Ldap_Node_RootDse

The following methods are available on all vendor-specific subclasses.

Zend_Ldap_Node_RootDse includes the magic property accessors __get() and __isset() to access the attributes by their name. They proxy to Zend_Ldap_Node_RootDse::getAttribute() and Zend_Ldap_Node_RootDse::existsAttribute() respectively. __set() and __unset() are also implemented but they throw a BadMethodCallException as modifications are not allowed on RootDSE nodes. Furthermore the class implements ArrayAccess for array-style-access to the attributes. offsetSet() and offsetUnset() also throw a BadMethodCallException due ro obvious reasons.

Zend_Ldap_Node_RootDse API
Method | Description
Zend_Ldap_Dn getDn() | Gets the DN of the current node as a Zend_Ldap_Dn.
string getDnString(string $caseFold) | Gets the DN of the current node as a string.
array getDnArray(string $caseFold) | Gets the DN of the current node as an array.
string getRdnString(string $caseFold) | Gets the RDN of the current node as a string.
array getRdnArray(string $caseFold) | Gets the RDN of the current node as an array.
array getObjectClass() | Returns the objectClass of the node.
string toString() | Returns the DN of the current node - proxies to Zend_Ldap_Dn::getDnString().
string __toString() | Casts to string representation - proxies to Zend_Ldap_Dn::toString().
array toArray(boolean $includeSystemAttributes) | Returns an array representation of the current node. If $includeSystemAttributes is FALSE (defaults to TRUE) the system specific attributes are stripped from the array. Unlike Zend_Ldap_Node_RootDse::getAttributes() the resulting array contains the DN with key 'dn'.
string toJson(boolean $includeSystemAttributes) | Returns a JSON representation of the current node using Zend_Ldap_Node_RootDse::toArray().
array getData(boolean $includeSystemAttributes) | Returns the node's attributes. The array contains all attributes in its internal format (no conversion).
boolean existsAttribute(string $name, boolean $emptyExists) | Checks whether a given attribute exists. If $emptyExists is FALSE, empty attributes (containing only array()) are treated as non-existent returning FALSE. If $emptyExists is TRUE, empty attributes are treated as existent returning TRUE. In this case the method returns FALSE only if the attribute name is missing in the key-collection.
boolean attributeHasValue(string $name, mixed|array $value) | Checks if the given value(s) exist in the attribute. The method returns TRUE only if all values in $value are present in the attribute. Comparison is done strictly (respecting the data type).
integer count() | Returns the number of attributes in the node. Implements Countable.
mixed getAttribute(string $name, integer|null $index) | Gets a LDAP attribute. Data conversion is applied using Zend_Ldap_Attribute::getAttribute().
array getAttributes(boolean $includeSystemAttributes) | Gets all attributes of node. If $includeSystemAttributes is FALSE (defaults to TRUE) the system specific attributes are stripped from the array.
array|integer getDateTimeAttribute(string $name, integer|null $index) | Gets a LDAP date/time attribute. Data conversion is applied using Zend_Ldap_Attribute::getDateTimeAttribute().
Zend_Ldap_Node_RootDse reload(Zend_Ldap $ldap) | Reloads the current node's attributes from the given LDAP server.
Zend_Ldap_Node_RootDse create(Zend_Ldap $ldap) | Factory method to create the RootDSE.
array getNamingContexts() | Gets the namingContexts.
string|null getSubschemaSubentry() | Gets the subschemaSubentry.
boolean supportsVersion(string|int|array $versions) | Determines if the LDAP version is supported.
boolean supportsSaslMechanism(string|array $mechlist) | Determines if the sasl mechanism is supported.
integer getServerType() Gets the server type. Returns
Zend_Ldap_Node_RootDse::SERVER_TYPE_GENERIC

for unknown LDAP servers

Zend_Ldap_Node_RootDse::SERVER_TYPE_OPENLDAP

for OpenLDAP servers

Zend_Ldap_Node_RootDse::SERVER_TYPE_ACTIVEDIRECTORY

for Microsoft ActiveDirectory servers

Zend_Ldap_Node_RootDse::SERVER_TYPE_EDIRECTORY

For Novell eDirectory servers
Zend_Ldap_Dn getSchemaDn() | Returns the schema DN.

OpenLDAP

Additionally the common methods above apply to instances of Zend_Ldap_Node_RootDse_OpenLdap.

Note: Refer to » LDAP Operational Attributes and Objectsfor information on the attributes of OpenLDAP RootDSE.

Zend_Ldap_Node_RootDse_OpenLdap API
Method | Description
integer getServerType() | Gets the server type. Returns Zend_Ldap_Node_RootDse::SERVER_TYPE_OPENLDAP
string|null getConfigContext() | Gets the configContext.
string|null getMonitorContext() | Gets the monitorContext.
boolean supportsControl(string|array $oids) | Determines if the control is supported.
boolean supportsExtension(string|array $oids) | Determines if the extension is supported.
boolean supportsFeature(string|array $oids) | Determines if the feature is supported.

ActiveDirectory

Additionally the common methods above apply to instances of Zend_Ldap_Node_RootDse_ActiveDirectory.

Note: Refer to » RootDSEfor information on the attributes of Microsoft ActiveDirectory RootDSE.

Zend_Ldap_Node_RootDse_ActiveDirectory API
Method | Description
integer getServerType() | Gets the server type. Returns Zend_Ldap_Node_RootDse::SERVER_TYPE_ACTIVEDIRECTORY
string|null getConfigurationNamingContext() | Gets the configurationNamingContext.
string|null getCurrentTime() | Gets the currentTime.
string|null getDefaultNamingContext() | Gets the defaultNamingContext.
string|null getDnsHostName() | Gets the dnsHostName.
string|null getDomainControllerFunctionality() | Gets the domainControllerFunctionality.
string|null getDomainFunctionality() | Gets the domainFunctionality.
string|null getDsServiceName() | Gets the dsServiceName.
string|null getForestFunctionality() | Gets the forestFunctionality.
string|null getHighestCommittedUSN() | Gets the highestCommittedUSN.
string|null getIsGlobalCatalogReady() | Gets the isGlobalCatalogReady.
string|null getIsSynchronized() | Gets the isSynchronized.
string|null getLdapServiceName() | Gets the ldapServiceName.
string|null getRootDomainNamingContext() | Gets the rootDomainNamingContext.
string|null getSchemaNamingContext() | Gets the schemaNamingContext.
string|null getServerName() | Gets the serverName.
boolean supportsCapability(string|array $oids) | Determines if the capability is supported.
boolean supportsControl(string|array $oids) | Determines if the control is supported.
boolean supportsPolicy(string|array $policies) | Determines if the version is supported.

eDirectory

Additionally the common methods above apply to instances of Zend_Ldap_Node_RootDse_eDirectory.

Note: Refer to » Getting Information about the LDAP Serverfor information on the attributes of Novell eDirectory RootDSE.

Zend_Ldap_Node_RootDse_eDirectory API
Method | Description
integer getServerType() | Gets the server type. Returns Zend_Ldap_Node_RootDse::SERVER_TYPE_EDIRECTORY
boolean supportsExtension(string|array $oids) | Determines if the extension is supported.
string|null getVendorName() | Gets the vendorName.
string|null getVendorVersion() | Gets the vendorVersion.
string|null getDsaName() | Gets the dsaName.
string|null getStatisticsErrors() | Gets the server statistics "errors".
string|null getStatisticsSecurityErrors() | Gets the server statistics "securityErrors".
string|null getStatisticsChainings() | Gets the server statistics "chainings".
string|null getStatisticsReferralsReturned() | Gets the server statistics "referralsReturned".
string|null getStatisticsExtendedOps() | Gets the server statistics "extendedOps".
string|null getStatisticsAbandonOps() | Gets the server statistics "abandonOps".
string|null getStatisticsWholeSubtreeSearchOps() | Gets the server statistics "wholeSubtreeSearchOps".

Zend_Ldap_Node_Schema

The following methods are available on all vendor-specific subclasses.

Zend_Ldap_Node_Schema includes the magic property accessors __get() and __isset() to access the attributes by their name. They proxy to Zend_Ldap_Node_Schema::getAttribute() and Zend_Ldap_Node_Schema::existsAttribute() respectively. __set() and __unset() are also implemented, but they throw a BadMethodCallException as modifications are not allowed on RootDSE nodes. Furthermore the class implements ArrayAccess for array-style-access to the attributes. offsetSet() and offsetUnset() also throw a BadMethodCallException due to obvious reasons.

Zend_Ldap_Node_Schema API
Method | Description
Zend_Ldap_Dn getDn() | Gets the DN of the current node as a Zend_Ldap_Dn.
string getDnString(string $caseFold) | Gets the DN of the current node as a string.
array getDnArray(string $caseFold) | Gets the DN of the current node as an array.
string getRdnString(string $caseFold) | Gets the RDN of the current node as a string.
array getRdnArray(string $caseFold) | Gets the RDN of the current node as an array.
array getObjectClass() | Returns the objectClass of the node.
string toString() | Returns the DN of the current node - proxies to Zend_Ldap_Dn::getDnString().
string __toString() | Casts to string representation - proxies to Zend_Ldap_Dn::toString().
array toArray(boolean $includeSystemAttributes) | Returns an array representation of the current node. If $includeSystemAttributes is FALSE (defaults to TRUE), the system specific attributes are stripped from the array. Unlike Zend_Ldap_Node_Schema::getAttributes(), the resulting array contains the DN with key 'dn'.
string toJson(boolean $includeSystemAttributes) | Returns a JSON representation of the current node using Zend_Ldap_Node_Schema::toArray().
array getData(boolean $includeSystemAttributes) | Returns the node's attributes. The array contains all attributes in its internal format (no conversion).
boolean existsAttribute(string $name, boolean $emptyExists) | Checks whether a given attribute exists. If $emptyExists is FALSE, empty attributes (containing only array()) are treated as non-existent returning FALSE. If $emptyExists is TRUE, empty attributes are treated as existent returning TRUE. In this case the method returns FALSE only if the attribute name is missing in the key-collection.
boolean attributeHasValue(string $name, mixed|array $value) | Checks if the given value(s) exist in the attribute. The method returns TRUE only if all values in $value are present in the attribute. Comparison is done strictly (respecting the data type).
integer count() | Returns the number of attributes in the node. Implements Countable.
mixed getAttribute(string $name, integer|null $index) | Gets a LDAP attribute. Data conversion is applied using Zend_Ldap_Attribute::getAttribute().
array getAttributes(boolean $includeSystemAttributes) | Gets all attributes of node. If $includeSystemAttributes is FALSE (defaults to TRUE) the system specific attributes are stripped from the array.
array|integer getDateTimeAttribute(string $name, integer|null $index) | Gets a LDAP date/time attribute. Data conversion is applied using Zend_Ldap_Attribute::getDateTimeAttribute().
Zend_Ldap_Node_Schema reload(Zend_Ldap $ldap) | Reloads the current node's attributes from the given LDAP server.
Zend_Ldap_Node_Schema create(Zend_Ldap $ldap) | Factory method to create the Schema node.
array getAttributeTypes() | Gets the attribute types as an array of .
array getObjectClasses() | Gets the object classes as an array of Zend_Ldap_Node_Schema_ObjectClass_Interface.
Zend_Ldap_Node_Schema_AttributeType_Interface API
Method | Description
string getName() | Gets the attribute name.
string getOid() | Gets the attribute OID.
string getSyntax() | Gets the attribute syntax.
int|null getMaxLength() | Gets the attribute maximum length.
boolean isSingleValued() | Returns if the attribute is single-valued.
string getDescription() | Gets the attribute description
Zend_Ldap_Node_Schema_ObjectClass_Interface API
Method | Description
string getName() | Returns the objectClass name.
string getOid() | Returns the objectClass OID.
array getMustContain() | Returns the attributes that this objectClass must contain.
array getMayContain() | Returns the attributes that this objectClass may contain.
string getDescription() | Returns the attribute description
integer getType() Returns the objectClass type. The method returns one of the following values:
Zend_Ldap_Node_Schema::OBJECTCLASS_TYPE_UNKNOWN

for unknown class types

Zend_Ldap_Node_Schema::OBJECTCLASS_TYPE_STRUCTURAL

for structural classes

Zend_Ldap_Node_Schema::OBJECTCLASS_TYPE_ABSTRACT

for abstract classes

Zend_Ldap_Node_Schema::OBJECTCLASS_TYPE_AUXILIARY

for auxiliary classes
array getParentClasses() | Returns the parent objectClasses of this class. This includes structural, abstract and auxiliary objectClasses.

Classes representing attribute types and object classes extend Zend_Ldap_Node_Schema_Item which provides some core methods to access arbitrary attributes on the underlying LDAP node. Zend_Ldap_Node_Schema_Item includes the magic property accessors __get() and __isset() to access the attributes by their name. Furthermore the class implements ArrayAccess for array-style-access to the attributes. offsetSet() and offsetUnset() throw a BadMethodCallException as modifications are not allowed on schema information nodes.

Zend_Ldap_Node_Schema_Item API
Method | Description
array getData() | Gets all the underlying data from the schema information node.
integer count() | Returns the number of attributes in this schema information node. Implements Countable.

OpenLDAP

Additionally the common methods above apply to instances of Zend_Ldap_Node_Schema_OpenLDAP.

Zend_Ldap_Node_Schema_OpenLDAP API
Method | Description
array getLdapSyntaxes() | Gets the LDAP syntaxes.
array getMatchingRules() | Gets the matching rules.
array getMatchingRuleUse() | Gets the matching rule use.
Zend_Ldap_Node_Schema_AttributeType_OpenLDAP API
Method | Description
Zend_Ldap_Node_Schema_AttributeType_OpenLdap|null getParent() | Returns the parent attribute type in the inheritance tree if one exists.
Zend_Ldap_Node_Schema_ObjectClass_OpenLDAP API
Method | Description
array getParents() | Returns the parent object classes in the inheritance tree if one exists. The returned array is an array of Zend_Ldap_Node_Schema_ObjectClass_OpenLdap.

ActiveDirectory

Note: Schema browsing on ActiveDirectory servers
 Due to restrictions on Microsoft ActiveDirectory servers regarding the number of entries returned by generic search routines and due to the structure of the ActiveDirectory schema repository, schema browsing is currently not available for Microsoft ActiveDirectory servers.

Zend_Ldap_Node_Schema_ActiveDirectory does not provide any additional methods.

Zend_Ldap_Node_Schema_AttributeType_ActiveDirectory API
Zend_Ldap_Node_Schema_AttributeType_ActiveDirectory does not provide any additional methods.
Zend_Ldap_Node_Schema_ObjectClass_ActiveDirectory API
Zend_Ldap_Node_Schema_ObjectClass_ActiveDirectory does not provide any additional methods.

Zend_Ldif_Encoder

Zend_Ldif_Encoder API
Method | Description
array decode(string $string) | Decodes the string $string into an array of LDIF items.
string encode(scalar|array|Zend_Ldap_Node $value, array $options) Encode $value into a LDIF representation. $options is an array that may contain the following keys:
'sort'

Sort the given attributes with dn following objectClass and following all other attributes sorted alphabetically. TRUE by default.

'version'

The LDIF format version. 1 by default.

'wrap'

The line-length. 78 by default to conform to the LDIF specification.

Introduction
Zend_Ldap
Zend Framework手册 中文版
Usage Scenarios
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Ldap
  • Introduction
  • API overview
  • Usage Scenarios
  • Tools
  • Object oriented access to the LDAP tree using Zend_Ldap_Node
  • Getting information from the LDAP server
  • Serializing LDAP data to and from LDIF


Usage Scenarios - Zend Framework Manual

API overview
Zend_Ldap
Zend Framework手册 中文版
Tools

Usage Scenarios

Authentication scenarios

OpenLDAP

ActiveDirectory

Basic CRUD operations

Retrieving data from the LDAP

Example #1 Getting an entry by its DN

  1. $options = array(/* ... */);
  2. $ldap = new Zend_Ldap($options);
  3. $ldap->bind();
  4. $hm = $ldap->getEntry('cn=Hugo Müller,ou=People,dc=my,dc=local');
  5. /*
  6. $hm is an array of the following structure
  7. array(
  8.     'dn'          => 'cn=Hugo Müller,ou=People,dc=my,dc=local',
  9.     'cn'          => array('Hugo Müller'),
  10.     'sn'          => array('Müller'),
  11.     'objectclass' => array('inetOrgPerson', 'top'),
  12.     ...
  13. )
  14. */

Example #2 Check for the existence of a given DN

  1. $options = array(/* ... */);
  2. $ldap = new Zend_Ldap($options);
  3. $ldap->bind();
  4. $isThere = $ldap->exists('cn=Hugo Müller,ou=People,dc=my,dc=local');

Example #3 Count children of a given DN

  1. $options = array(/* ... */);
  2. $ldap = new Zend_Ldap($options);
  3. $ldap->bind();
  4. $childrenCount = $ldap->countChildren(
  5.                             'cn=Hugo Müller,ou=People,dc=my,dc=local');

Example #4 Searching the LDAP tree

  1. $options = array(/* ... */);
  2. $ldap = new Zend_Ldap($options);
  3. $ldap->bind();
  4. $result = $ldap->search('(objectclass=*)',
  5.                         'ou=People,dc=my,dc=local',
  6.                         Zend_Ldap_Ext::SEARCH_SCOPE_ONE);
  7. foreach ($result as $item) {
  8.     echo $item["dn"] . ': ' . $item['cn'][0] . PHP_EOL;
  9. }

Adding data to the LDAP

Example #5 Add a new entry to the LDAP

  1. $options = array(/* ... */);
  2. $ldap = new Zend_Ldap($options);
  3. $ldap->bind();
  4. $entry = array();
  5. Zend_Ldap_Attribute::setAttribute($entry, 'cn', 'Hans Meier');
  6. Zend_Ldap_Attribute::setAttribute($entry, 'sn', 'Meier');
  7. Zend_Ldap_Attribute::setAttribute($entry, 'objectClass', 'inetOrgPerson');
  8. $ldap->add('cn=Hans Meier,ou=People,dc=my,dc=local', $entry);

Deleting from the LDAP

Example #6 Delete an existing entry from the LDAP

  1. $options = array(/* ... */);
  2. $ldap = new Zend_Ldap($options);
  3. $ldap->bind();
  4. $ldap->delete('cn=Hans Meier,ou=People,dc=my,dc=local');

Updating the LDAP

Example #7 Update an existing entry on the LDAP

  1. $options = array(/* ... */);
  2. $ldap = new Zend_Ldap($options);
  3. $ldap->bind();
  4. $hm = $ldap->getEntry('cn=Hugo Müller,ou=People,dc=my,dc=local');
  5. Zend_Ldap_Attribute::setAttribute($hm, 'mail', 'mueller@my.local');
  6. Zend_Ldap_Attribute::setPassword($hm,
  7.                                  'newPa$$w0rd',
  8.                                  Zend_Ldap_Attribute::PASSWORD_HASH_SHA1);
  9. $ldap->update('cn=Hugo Müller,ou=People,dc=my,dc=local', $hm);

Extended operations

Copy and move entries in the LDAP

Example #8 Copy a LDAP entry recursively with all its descendants

  1. $options = array(/* ... */);
  2. $ldap = new Zend_Ldap($options);
  3. $ldap->bind();
  4. $ldap->copy('cn=Hugo Müller,ou=People,dc=my,dc=local',
  5.             'cn=Hans Meier,ou=People,dc=my,dc=local',
  6.             true);

Example #9 Move a LDAP entry recursively with all its descendants to a different subtree

  1. $options = array(/* ... */);
  2. $ldap = new Zend_Ldap($options);
  3. $ldap->bind();
  4. $ldap->moveToSubtree('cn=Hugo Müller,ou=People,dc=my,dc=local',
  5.                      'ou=Dismissed,dc=my,dc=local',
  6.                      true);
API overview
Zend_Ldap
Zend Framework手册 中文版
Tools
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Ldap
  • Introduction
  • API overview
  • Usage Scenarios
  • Tools
  • Object oriented access to the LDAP tree using Zend_Ldap_Node
  • Getting information from the LDAP server
  • Serializing LDAP data to and from LDIF


Tools - Zend Framework Manual

Usage Scenarios
Zend_Ldap
Zend Framework手册 中文版
Object oriented access to the LDAP tree using Zend_Ldap_Node

Tools

Creation and modification of DN strings

Using the filter API to create search filters

Example #1 Create simple LDAP filters

  1. $f1  = Zend_Ldap_Filter::equals('name', 'value');         // (name=value)
  2. $f2  = Zend_Ldap_Filter::begins('name', 'value');         // (name=value*)
  3. $f3  = Zend_Ldap_Filter::ends('name', 'value');           // (name=*value)
  4. $f4  = Zend_Ldap_Filter::contains('name', 'value');       // (name=*value*)
  5. $f5  = Zend_Ldap_Filter::greater('name', 'value');        // (name>value)
  6. $f6  = Zend_Ldap_Filter::greaterOrEqual('name', 'value'); // (name>=value)
  7. $f7  = Zend_Ldap_Filter::less('name', 'value');           // (name<value)
  8. $f8  = Zend_Ldap_Filter::lessOrEqual('name', 'value');    // (name<=value)
  9. $f9  = Zend_Ldap_Filter::approx('name', 'value');         // (name~=value)
  10. $f10 = Zend_Ldap_Filter::any('name');                     // (name=*)

Example #2 Create more complex LDAP filters

  1. $f1 = Zend_Ldap_Filter::ends('name', 'value')->negate(); // (!(name=*value))
  2.
  3. $f2 = Zend_Ldap_Filter::equals('name', 'value');
  4. $f3 = Zend_Ldap_Filter::begins('name', 'value');
  5. $f4 = Zend_Ldap_Filter::ends('name', 'value');
  6.
  7. // (&(name=value)(name=value*)(name=*value))
  8. $f5 = Zend_Ldap_Filter::andFilter($f2, $f3, $f4);
  9.
  10. // (|(name=value)(name=value*)(name=*value))
  11. $f6 = Zend_Ldap_Filter::orFilter($f2, $f3, $f4);

Modify LDAP entries using the Attribute API

Usage Scenarios
Zend_Ldap
Zend Framework手册 中文版
Object oriented access to the LDAP tree using Zend_Ldap_Node
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Ldap
  • Introduction
  • API overview
  • Usage Scenarios
  • Tools
  • Object oriented access to the LDAP tree using Zend_Ldap_Node
  • Getting information from the LDAP server
  • Serializing LDAP data to and from LDIF


Object oriented access to the LDAP tree using Zend_Ldap_Node - Zend Framework Manual

Tools
Zend_Ldap
Zend Framework手册 中文版
Getting information from the LDAP server

Object oriented access to the LDAP tree using Zend_Ldap_Node

Basic CRUD operations

Retrieving data from the LDAP

Getting a node by its DN

Searching a node's subtree

Adding a new node to the LDAP

Deleting a node from the LDAP

Updating a node on the LDAP

Extended operations

Copy and move nodes in the LDAP

Tree traversal

Example #1 Traverse LDAP tree recursively

  1. $options = array(/* ... */);
  2. $ldap = new Zend_Ldap($options);
  3. $ldap->bind();
  4. $ri = new RecursiveIteratorIterator($ldap->getBaseNode(),
  5.                                     RecursiveIteratorIterator::SELF_FIRST);
  6. foreach ($ri as $rdn => $n) {
  7.     var_dump($n);
  8. }
Tools
Zend_Ldap
Zend Framework手册 中文版
Getting information from the LDAP server
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Ldap
  • Introduction
  • API overview
  • Usage Scenarios
  • Tools
  • Object oriented access to the LDAP tree using Zend_Ldap_Node
  • Getting information from the LDAP server
  • Serializing LDAP data to and from LDIF


Getting information from the LDAP server - Zend Framework Manual

Object oriented access to the LDAP tree using Zend_Ldap_Node
Zend_Ldap
Zend Framework手册 中文版
Serializing LDAP data to and from LDIF

Getting information from the LDAP server

RootDSE

See the following documents for more information on the attributes contained within the RootDSE for a given LDAP server.

  • » OpenLDAP

  • » Microsoft ActiveDirectory

  • » Novell eDirectory

Example #1 Getting hands on the RootDSE

  1. $options = array(/* ... */);
  2. $ldap = new Zend_Ldap($options);
  3. $rootdse = $ldap->getRootDse();
  4. $serverType = $rootdse->getServerType();

Schema Browsing

Example #2 Getting hands on the server schema

  1. $options = array(/* ... */);
  2. $ldap = new Zend_Ldap($options);
  3. $schema = $ldap->getSchema();
  4. $classes = $schema->getObjectClasses();

OpenLDAP

ActiveDirectory

Note: Schema browsing on ActiveDirectory servers
 Due to restrictions on Microsoft ActiveDirectory servers regarding the number of entries returned by generic search routines and due to the structure of the ActiveDirectory schema repository, schema browsing is currently not available for Microsoft ActiveDirectory servers.

Object oriented access to the LDAP tree using Zend_Ldap_Node
Zend_Ldap
Zend Framework手册 中文版
Serializing LDAP data to and from LDIF
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Ldap
  • Introduction
  • API overview
  • Usage Scenarios
  • Tools
  • Object oriented access to the LDAP tree using Zend_Ldap_Node
  • Getting information from the LDAP server
  • Serializing LDAP data to and from LDIF


Serializing LDAP data to and from LDIF - Zend Framework Manual

Getting information from the LDAP server
Zend_Ldap
Zend Framework手册 中文版
Zend_Loader

Serializing LDAP data to and from LDIF

Serialize a LDAP entry to LDIF

  1. $data = array(
  2.     'dn'                         => 'uid=rogasawara,ou=営業部,o=Airius',
  3.     'objectclass'                => array('top',
  4.                                           'person',
  5.                                           'organizationalPerson',
  6.                                           'inetOrgPerson'),
  7.     'uid'                        => array('rogasawara'),
  8.     'mail'                       => array('rogasawara@airius.co.jp'),
  9.     'givenname;lang-ja'          => array('ロドニー'),
  10.     'sn;lang-ja'                 => array('小笠原'),
  11.     'cn;lang-ja'                 => array('小笠原 ロドニー'),
  12.     'title;lang-ja'              => array('営業部 部長'),
  13.     'preferredlanguage'          => array('ja'),
  14.     'givenname'                  => array('ロドニー'),
  15.     'sn'                         => array('小笠原'),
  16.     'cn'                         => array('小笠原 ロドニー'),
  17.     'title'                      => array('営業部 部長'),
  18.     'givenname;lang-ja;phonetic' => array('ろどにー'),
  19.     'sn;lang-ja;phonetic'        => array('おがさわら'),
  20.     'cn;lang-ja;phonetic'        => array('おがさわら ろどにー'),
  21.     'title;lang-ja;phonetic'     => array('えいぎょうぶ ぶちょう'),
  22.     'givenname;lang-en'          => array('Rodney'),
  23.     'sn;lang-en'                 => array('Ogasawara'),
  24.     'cn;lang-en'                 => array('Rodney Ogasawara'),
  25.     'title;lang-en'              => array('Sales, Director'),
  26. );
  27. $ldif = Zend_Ldap_Ldif_Encoder::encode($data, array('sort' => false,
  28.                                                     'version' => null));
  29. /*
  30. $ldif contains:
  31. dn:: dWlkPXJvZ2FzYXdhcmEsb3U95Za25qWt6YOoLG89QWlyaXVz
  32. objectclass: top
  33. objectclass: person
  34. objectclass: organizationalPerson
  35. objectclass: inetOrgPerson
  36. uid: rogasawara
  37. mail: rogasawara@airius.co.jp
  38. givenname;lang-ja:: 44Ot44OJ44OL44O8
  39. sn;lang-ja:: 5bCP56yg5Y6f
  40. cn;lang-ja:: 5bCP56yg5Y6fIOODreODieODi+ODvA==
  41. title;lang-ja:: 5Za25qWt6YOoIOmDqOmVtw==
  42. preferredlanguage: ja
  43. givenname:: 44Ot44OJ44OL44O8
  44. sn:: 5bCP56yg5Y6f
  45. cn:: 5bCP56yg5Y6fIOODreODieODi+ODvA==
  46. title:: 5Za25qWt6YOoIOmDqOmVtw==
  47. givenname;lang-ja;phonetic:: 44KN44Gp44Gr44O8
  48. sn;lang-ja;phonetic:: 44GK44GM44GV44KP44KJ
  49. cn;lang-ja;phonetic:: 44GK44GM44GV44KP44KJIOOCjeOBqeOBq+ODvA==
  50. title;lang-ja;phonetic:: 44GI44GE44GO44KH44GG44G2IOOBtuOBoeOCh+OBhg==
  51. givenname;lang-en: Rodney
  52. sn;lang-en: Ogasawara
  53. cn;lang-en: Rodney Ogasawara
  54. title;lang-en: Sales, Director
  55. */

Deserialize a LDIF string into a LDAP entry

  1. $ldif = "dn:: dWlkPXJvZ2FzYXdhcmEsb3U95Za25qWt6YOoLG89QWlyaXVz
  2. objectclass: top
  3. objectclass: person
  4. objectclass: organizationalPerson
  5. objectclass: inetOrgPerson
  6. uid: rogasawara
  7. mail: rogasawara@airius.co.jp
  8. givenname;lang-ja:: 44Ot44OJ44OL44O8
  9. sn;lang-ja:: 5bCP56yg5Y6f
  10. cn;lang-ja:: 5bCP56yg5Y6fIOODreODieODi+ODvA==
  11. title;lang-ja:: 5Za25qWt6YOoIOmDqOmVtw==
  12. preferredlanguage: ja
  13. givenname:: 44Ot44OJ44OL44O8
  14. sn:: 5bCP56yg5Y6f
  15. cn:: 5bCP56yg5Y6fIOODreODieODi+ODvA==
  16. title:: 5Za25qWt6YOoIOmDqOmVtw==
  17. givenname;lang-ja;phonetic:: 44KN44Gp44Gr44O8
  18. sn;lang-ja;phonetic:: 44GK44GM44GV44KP44KJ
  19. cn;lang-ja;phonetic:: 44GK44GM44GV44KP44KJIOOCjeOBqeOBq+ODvA==
  20. title;lang-ja;phonetic:: 44GI44GE44GO44KH44GG44G2IOOBtuOBoeOCh+OBhg==
  21. givenname;lang-en: Rodney
  22. sn;lang-en: Ogasawara
  23. cn;lang-en: Rodney Ogasawara
  24. title;lang-en: Sales, Director";
  25. $data = Zend_Ldap_Ldif_Encoder::decode($ldif);
  26. /*
  27. $data = array(
  28.     'dn'                         => 'uid=rogasawara,ou=営業部,o=Airius',
  29.     'objectclass'                => array('top',
  30.                                           'person',
  31.                                           'organizationalPerson',
  32.                                           'inetOrgPerson'),
  33.     'uid'                        => array('rogasawara'),
  34.     'mail'                       => array('rogasawara@airius.co.jp'),
  35.     'givenname;lang-ja'          => array('ロドニー'),
  36.     'sn;lang-ja'                 => array('小笠原'),
  37.     'cn;lang-ja'                 => array('小笠原 ロドニー'),
  38.     'title;lang-ja'              => array('営業部 部長'),
  39.     'preferredlanguage'          => array('ja'),
  40.     'givenname'                  => array('ロドニー'),
  41.     'sn'                         => array('小笠原'),
  42.     'cn'                         => array('小笠原 ロドニー'),
  43.     'title'                      => array('営業部 部長'),
  44.     'givenname;lang-ja;phonetic' => array('ろどにー'),
  45.     'sn;lang-ja;phonetic'        => array('おがさわら'),
  46.     'cn;lang-ja;phonetic'        => array('おがさわら ろどにー'),
  47.     'title;lang-ja;phonetic'     => array('えいぎょうぶ ぶちょう'),
  48.     'givenname;lang-en'          => array('Rodney'),
  49.     'sn;lang-en'                 => array('Ogasawara'),
  50.     'cn;lang-en'                 => array('Rodney Ogasawara'),
  51.     'title;lang-en'              => array('Sales, Director'),
  52. );
  53. */
Getting information from the LDAP server
Zend_Ldap
Zend Framework手册 中文版
Zend_Loader
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Ldap
  • Introduction
  • API overview
  • Usage Scenarios
  • Tools
  • Object oriented access to the LDAP tree using Zend_Ldap_Node
  • Getting information from the LDAP server
  • Serializing LDAP data to and from LDIF


Zend_Loader - Zend Framework Manual

Serializing LDAP data to and from LDIF
Zend Framework Reference
Zend Framework手册 中文版
动态加载文件和类

Zend_Loader

Table of Contents
  • 动态加载文件和类
  • The Autoloader
  • Resource Autoloaders
  • 加载插件
Serializing LDAP data to and from LDIF
Zend Framework Reference
Zend Framework手册 中文版
动态加载文件和类
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


动态加载文件和类 - Zend Framework Manual

Zend_Loader
Zend_Loader
Zend Framework手册 中文版
The Autoloader

动态加载文件和类

Zend_Loader类可以帮助你动态加载文件。

Tip

Zend_Loader vs. require_once()

Zend_Loader 最适合于加载的文件名是变量的情况（例如你要加载的文件的名称来自于用户的输入或者某个方法的参数）。如果你加载的文件名或类名是一个常量（即确定的文件，如/lib/test.php），则使用 Zend_Loader 并不比传统的PHP函数 » require_once()有什么优势。

加载文件

静态方法 Zend_Loader::loadFile() 加载PHP文件，被加载的文件可包含任何 PHP 代码。它其实是将PHP的» include()函数封装而成的一个静态方法。当包含文件失败时，会抛出异常Zend_Exception，例如指定的文件不存在。

Example #1 loadFile() 方法范例

Zend_Loader::loadFile($filename, $dirs=null, $once=false);

$filename参数指定需要加载的文件，注意$filename不需要指定任何路径，只需要文件名即可。ZF会对文件作安全性检查。$filename 只能由字母，数字，连接符-,下划线_及英文句号.组成(半角)。$dirs参数则不限，可以使用中文等。

$dirs 参数用来指定文件所在目录，可以是一个字符串或者数组。如果为 NULL，则程序将会到系统的 include_path 下寻找文件是否存在（include_path可在php.ini中设置--Haohappy注），如果是字符串或数组，则会到指定的目录下去找，然后才是 include_path。

$once 参数为布尔类型，如果为 TRUE，Zend_Loader::loadFile() 使用 PHP 函数 » include_once() 加载文件，否则就是 PHP 函数 » include()。（本参数只能是true或false，两者区别就和include()和include_once()的区别一样。）

加载类

静态方法Zend_Loader::loadClass($class, $dirs)用来加载一个 PHP 类文件，该文件名格式为“$className.php”（也就是说加载的文件名称必须和文件中的类同名）。loadClass()会检查文件中的类是否存在。

Example #2 Example of loadClass() method

Zend_Loader::loadClass('Container_Tree',
    array(
        '/home/production/mylib',
        '/home/production/myapp'
    )
);

类名将会根据下划线（作为目录分隔线）对应到相应目录下的PHP文件，并加上'.php'，比如Container_Tree会指向Container\\Tree.php。

如果$dirs是一个字符串或数组， Zend_Loader::loadClass()会根据顺序查找相应目录，并加载第一个匹配的文件。如果文件不存在，则会查找 inculde_path 指定的目录。

如果文件不存在或者文件中相应的类不存在，那么 Zend_Loader::loadClass() 就会抛出一个 Zend_Exception 异常。

Zend_Loader::loadFile() 用来加载文件，所以类名中只能包含字母数字、连接符('-')、下划线('_')和句点('.')。

判定某个文件是否可读

静态方法Zend_Loader::isReadable($pathname)判定某个文件是否存在并可读，可读则返回 TRUE ，否则返回 FALSE。

Example #3 isReadable()示例：

if (Zend_Loader::isReadable($filename)) {
    // do something with $filename
}

$filename参数指定了要检查的文件名，包括路径信息。这个方法是将 PHP 函数» is_readable()封装而成的，is_readable() 不会自动查找 include_path 下的文件，而 Zend::isReadable() 可以。

使用 Autoloader

Zend_Loader 类包括一个可以用 PHP SPL autoloader 注册的方法。Zend_Loader::autoload() 是 callback 方法。为方便起见，Zend_Loader 提供 registerAutoload() 函数注册它的 autoload() 方法。如果 spl_autoload 扩展不在你的 PHP 环境中，那么 registerAutoload() 方法将抛出 Zend_Exception。

Example #4 注册 autoloader callback 方法范例

Zend_Loader::registerAutoload();

注册 Zend Framework autoload callback 后，可以不需要显式加载就可以从 Zend Framework 引用那些类。当应用一个类，autoload() 方法自动地使用 Zend_Loader::loadClass() 。

如果继承 Zend_Loader 类，可以给 registerAutoload() 一个可选的参数通过注册一个 autoload() 方法来指定类。

Example #5 从继承类注册 autoload callback 方法范例

因为在 PHP 中静态函数引用的语义，你必须实现 loadClass() 和 autoload()，autoload() 必须调用 self::loadClass()。如果 autoload() 方法代表它的父类调用 self::loadClass()，那么它调用在父类中的方法，而不是子类中。

class My_Loader extends Zend_Loader
{
    public static function loadClass($class, $dirs = null)
    {
        parent::loadClass($class, $dirs);
    }

    public static function autoload($class)
    {
        try {
            self::loadClass($class);
            return $class;
        } catch (Exception $e) {
            return false;
        }
    }
}

Zend_Loader::registerAutoload('My_Loader');

你可以删除 autoload callback，registerAutoload() 有个可选的第二个参数，缺省为 true 。如果这个参数是 false， 那么 autoload callback 从 SPL autoload 栈里 unregistered 掉而不是注册。

Zend_Loader
Zend_Loader
Zend Framework手册 中文版
The Autoloader
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Loader
  • 动态加载文件和类
  • The Autoloader
  • Resource Autoloaders
  • 加载插件


The Autoloader - Zend Framework Manual

动态加载文件和类
Zend_Loader
Zend Framework手册 中文版
Resource Autoloaders

The Autoloader

Zend_Loader_Autoloader introduces a comprehensive autoloading solution for Zend Framework. It has been designed with several goals in mind:

  • Provide a true namespace autoloader. (Previous incarnations intercepted all userland namespaces.)

  • Allow registering arbitrary callbacks as autoloaders, and manage them as a stack. (At the time of this writing, this overcomes some issues with spl_autoload, which does not allow re-registering a callback that utilizes an instance method.)

  • Allow optimistic matching of namespaces to provide faster class resolution.

Zend_Loader_Autoloader implements a singleton, making it unversally accessible. This provides the ability to register additional autoloaders from anywhere in your code as necessary.

Using the Autoloader

The first time an instance of the autoloader is retrieved, it registers itself with spl_autoload. You retrieve an instance using the getInstance() method:

  1. $autoloader = Zend_Loader_Autoloader::getInstance();

By default, the autoloader is configured to match the "Zend_" and "ZendX_" namespaces. If you have your own library code that uses your own namespace, you may register it with the autoloader using the registerNamespace() method. For instance, if your library code is prefixed with "My_", you could do so as follows:

  1. $autoloader->registerNamespace('My_');

Note: Namespace Prefixes
 You'll note that the previous example uses "My_" and not "My". This is because Zend_Loader_Autoloader is intended as a general purpose autoloader, and does not make the assumption that a given class prefix namespace includes an underscore. If your class namespace does include one, you should include it when registering your namespace.

You can also register arbitrary autoloader callbacks, optionally with a specific namespace (or group of namespaces). Zend_Loader_Autoloader will attempt to match these first before using its internal autoloading mechanism.

As an example, you may want to utilize one or more eZcomponents components with your Zend Framework application. To use its autoloading capabilities, push it onto the autoloader stack using pushAutoloader():

  1. $autoloader->pushAutoloader(array('ezcBase', 'autoload'), 'ezc');

This tells the autoloader to use the eZcomponents autoloader for classes beginning with "ezc".

You can use the unshiftAutoloader() method to add the autoloader to the beginning of the autoloader chain.

By default, Zend_Loader_Autoloader does no error suppression when using its internal autoloader, which utilizes Zend_Loader::loadClass(). Most of the time, this is exactly what you want. However, there may be cases where you want to suppress them. You can do this using suppressNotFoundWarnings():

  1. $autoloader->suppressNotFoundWarnings(true);

Finally, there may be times when you want the autoloader to load any namespace. For instance, PEAR libraries do not share a common namespace, making specifying individual namespaces difficult when many PEAR components are in use. You can use the setFallbackAutoloader() method to have the autoloader act as a catch-all:

  1. $autoloader->setFallbackAutoloader(true);

Note: Loading Classes from PHP Namespaces
 Starting in version 1.10.0, Zend Framework now allows loading classes from PHP namespaces. This support follows the same guidelines and implementation as that found in the » PHP Framework Interop Group PSR-0 reference implementation.
Under this guideline, the following rules apply:

  • Each namespace separator is converted to a DIRECTORY_SEPARATOR when loading from the file system.

  • Each "_" character in the CLASS NAME is converted to a DIRECTORY_SEPARATOR. The "_" character has no special meaning in the namespace.

  • The fully-qualified namespace and class is suffixed with ".php" when loading from the file system.

As examples:

  • \Doctrine\Common\IsolatedClassLoader => /path/to/project/lib/vendor/Doctrine/Common/IsolatedClassLoader.php

  • \namespace\package\Class_Name => /path/to/project/lib/vendor/namespace/package/Class/Name.php

  • \namespace\package_name\Class_Name => /path/to/project/lib/vendor/namespace/package_name/Class/Name.php

Selecting a Zend Framework version

Typically, you will use the version of Zend Framework that the autoloader you instantiate came with. However, when developing a project, it's often useful to track specific versions, major or minor branches, or just the latest version. Zend_Loader_Autoloader, as of version 1.10, offers some features to help manage this task.

Imagine the following scenario:

  • During development, you want to track the latest version of Zend Framework you have installed, so that you can ensure the application works when you upgrade between versions.

    When pushing to Quality Assurance, however, you need to have slightly more stability, so you want to use the latest installed revision of a specific minor version.

    Finally, when you push to production, you want to pin to a specific installed version, to ensure no breakage occurs if or when you add new versions of Zend Framework to you server.

The autoloader allows you to do this with the method setZfPath(). This method takes two arguments, a path to a set of Zend Framework installations, and a version to use. Once invoked, it prepends a path to the include_path pointing to the appropriate Zend Framework installation library.

The directory you specify as your path should have a tree such as the following:

  1. ZendFramework/
  2. |-- 1.9.2/
  3. |   |-- library/
  4. |-- ZendFramework-1.9.1-minimal/
  5. |   |-- library/
  6. |-- 1.8.4PL1/
  7. |   |-- library/
  8. |-- 1.8.4/
  9. |   |-- library/
  10. |-- ZendFramework-1.8.3/
  11. |   |-- library/
  12. |-- 1.7.8/
  13. |   |-- library/
  14. |-- 1.7.7/
  15. |   |-- library/
  16. |-- 1.7.6/
  17. |   |-- library/

(where path points to the directory "ZendFramework" in the above example)

Note that each subdirectory should contain the directory library, which contains the actual Zend Framework library code. The individual subdirectory names may be version numbers, or simply be the untarred contents of a standard Zend Framework distribution tarball/zipfile.

Now, let's address the use cases. In the first use case, in development, we want to track the latest source install. We can do that by passing "latest" as the version:

  1. $autoloader->setZfPath($path, 'latest');

In the example from above, this will map to the directory ZendFramework/1.9.2/library/; you can verify this by checking the return value of getZfPath().

In the second situation, for quality assurance, let's say we want to pin to the 1.8 minor release, using the latest install you have for that release. You can do so as follows:

  1. $autoloader->setZfPath($path, '1.8');

In this case, it will find the directory ZendFramework/1.8.4PL1/library/.

In the final case, for production, we'll pin to a specific version -- 1.7.7, since that was what was available when Quality Assurance tested prior to our release.

  1. $autoloader->setZfPath($path, '1.7.7');

Predictably, it finds the directory ZendFramework/1.7.7/library/.

You can also specify these values in the configuration file you use with Zend_Application. To do so, you'd specify the following information:

  1. [production]
  2. autoloaderZfPath = "path/to/ZendFramework"
  3. autoloaderZfVersion = "1.7.7"
  4.
  5. [qa]
  6. autoloaderZfVersion = "1.8"
  7.
  8. [development]
  9. autoloaderZfVersion = "latest"

Note the different environment sections, and the different version specified in each environment; these factors will allow Zend_Application to configure the autoloader appropriately.

Warning

Performance implications

For best performance, either do not use this feature, or specify a specific Zend Framework version (i.e., not "latest", a major revision such as "1", or a minor revision such as "1.8"). Otherwise, the autoloader will need to scan the provided path for directories matching the criteria -- a somewhat expensive operation to perform on each request.

The Autoloader Interface

Besides being able to specify arbitrary callbacks as autoloaders, Zend Framework also defines an interface autoloading classes may imlement, Zend_Loader_Autoloader_Interface:

  1. interface Zend_Loader_Autoloader_Interface
  2. {
  3.     public function autoload($class);
  4. }

When using this interface, you can simply pass a class instance to Zend_Loader_Autoloader's pushAutoloader() and unshiftAutoloader() methods:

  1. // Assume Foo_Autoloader implements Zend_Loader_Autoloader_Interface:
  2. $foo = new Foo_Autoloader();
  3.
  4. $autoloader->pushAutoloader($foo, 'Foo_');

Autoloader Reference

Below, please find a guide to the methods available in Zend_Loader_Autoloader.

Zend_Loader_Autoloader Methods
Method Return Value Parameters Description
getInstance() Zend_Loader_Autoloader N/A

Retrieve the Zend_Loader_Autoloader singleton instance. On first retrieval, it registers itself with spl_autoload. This method is static.

resetInstance() void N/A

Resets the state of the Zend_Loader_Autoloader singleton instance to it's original state, unregistering all autoloader callbacks and all registered namespaces.

autoload($class) string|FALSE

  • $class, required. A string class name to load.

Attempt to resolve a class name to a file and load it.

setDefaultAutoloader($callback) Zend_Loader_Autoloader

  • $callback, required.

Specify an alternate PHP callback to use for the default autoloader implementation.

getDefaultAutoloader() callback N/A

Retrieve the default autoloader implementation; by default, this is Zend_Loader::loadClass().

setAutoloaders(array $autoloaders) Zend_Loader_Autoloader

  • $autoloaders, required.

Set a list of concrete autoloaders to use in the autoloader stack. Each item in the autoloaders array must be a PHP callback.

getAutoloaders() Array N/A

Retrieve the internal autoloader stack.

getNamespaceAutoloaders($namespace) Array

  • $namespace, required

Fetch all autoloaders that have registered to load a specific namespace.

registerNamespace($namespace) Zend_Loader_Autoloader

  • $namespace, required.

Register one or more namespaces with the default autoloader. If $namespace is a string, it registers that namespace; if it's an array of strings, registers each as a namespace.

unregisterNamespace($namespace) Zend_Loader_Autoloader

  • $namespace, required.

Unregister one or more namespaces from the default autoloader. If $namespace is a string, it unregisters that namespace; if it's an array of strings, unregisters each as a namespace.

getRegisteredNamespaces() Array N/A

Returns an array of all namespaces registered with the default autoloader.

suppressNotFoundWarnings($flag = null) boolean|Zend_Loader_Autoloader

  • $flag, optional.

Set or retrieve the value of the flag used to indicate whether the default autoloader implementation should suppress "file not found" warnings. If no arguments or a NULL value is passed, returns a boolean indicating the status of the flag; if a boolean is passed, the flag is set to that value and the autoloader instance is returned (to allow method chaining).

setFallbackAutoloader($flag) Zend_Loader_Autoloader

  • $flag, required.

Set the value of the flag used to indicate whether or not the default autoloader should be used as a fallback or catch-all autoloader for all namespaces.

isFallbackAutoloader() Boolean N/A

Retrieve the value of the flag used to indicate whether or not the default autoloader should be used as a fallback or catch-all autoloader for all namespaces. By default, this is FALSE.

getClassAutoloaders($class) Array

  • $class, required.

Get the list of namespaced autoloaders that could potentially match the provided class. If none match, all global (non-namespaced) autoloaders are returned.

unshiftAutoloader($callback, $namespace = '') Zend_Loader_Autoloader

  • $callback, required. A valid PHP callback

  • $namespace, optional. A string representing a class prefix namespace.

Add a concrete autoloader implementation to the beginning of the internal autoloader stack. If a namespace is provided, that namespace will be used to match optimistically; otherwise, the autoloader will be considered a global autoloader.

pushAutoloader($callback, $namespace = '') Zend_Loader_Autoloader

  • $callback, required. A valid PHP callback

  • $namespace, optional. A string representing a class prefix namespace.

Add a concrete autoloader implementation to the end of the internal autoloader stack. If a namespace is provided, that namespace will be used to match optimistically; otherwise, the autoloader will be considered a global autoloader.

removeAutoloader($callback, $namespace = '') Zend_Loader_Autoloader

  • $callback, required. A valid PHP callback

  • $namespace, optional. A string representing a class prefix namespace, or an array of namespace strings.

Remove a concrete autoloader implementation from the internal autoloader stack. If a namespace or namespaces are provided, the callback will be removed from that namespace or namespaces only.

动态加载文件和类
Zend_Loader
Zend Framework手册 中文版
Resource Autoloaders
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Loader
  • 动态加载文件和类
  • The Autoloader
  • Resource Autoloaders
  • 加载插件


Resource Autoloaders - Zend Framework Manual

The Autoloader
Zend_Loader
Zend Framework手册 中文版
加载插件

Resource Autoloaders

Resource autoloaders are intended to manage namespaced library code that follow Zend Framework coding standard guidelines, but which do not have a 1:1 mapping between the class name and the directory structure. Their primary purpose is to facilitate autoloading application resource code, such as application-specific models, forms, and ACLs.

Resource autoloaders register with the autoloader on instantiation, with the namespace to which they are associated. This allows you to easily namespace code in specific directories, and still reap the benefits of autoloading.

Resource autoloader usage

Let's consider the following directory structure:

  1. path/to/some/directory/
  2.     acls/
  3.         Site.php
  4.     forms/
  5.         Login.php
  6.     models/
  7.         User.php

Within this directory, all code is prefixed with the namespace "My_". Within the "acls" subdirectory, the component prefix "Acl_" is added, giving a final class name of "My_Acl_Site". Similarly, the "forms" subdirectory maps to "Form_", giving "My_Form_Login". The "models" subdirectory has no component namespace, giving "My_User".

You can use a resource autoloader to autoload these classes. To instantiate the resource autoloader, you are required to pass at the minimum the base path and namespace for the resources it will be responsible for:

  1. $resourceLoader = new Zend_Loader_Autoloader_Resource(array(
  2.     'basePath'  => 'path/to/some/directory',
  3.     'namespace' => 'My',
  4. ));

Note: Base namespace
 In Zend_Loader_Autoloader, you are expected to provide the trailing underscore ("_") in your namespace if your autoloader will use it to match the namespace. Zend_Loader_Autoloader_Resource makes the assumption that all code you are autoloading will use an underscore separator between namespaces, components, and classes. As a result, you do not need to use the trailing underscore when registering a resource autoloader.

Now that we have setup the base resource autoloader, we can add some components to it to autoload. This is done using the addResourceType() method, which accepts three arguments: a resource "type", used internally as a reference name; the subdirectory path underneath the base path in which these resources live; and the component namespace to append to the base namespace. As an example, let's add each of our resource types.

  1. $resourceLoader->addResourceType('acl', 'acls/', 'Acl')
  2.                ->addResourceType('form', 'forms/', 'Form')
  3.                ->addResourceType('model', 'models/');

Alternately, you could pass these as an array to addResourceTypes(); the following is equivalent to the above:

  1. $resourceLoader->addResourceTypes(array(
  2.     'acl' => array(
  3.         'path'      => 'acls/',
  4.         'namespace' => 'Acl',
  5.     ),
  6.     'form' => array(
  7.         'path'      => 'forms/',
  8.         'namespace' => 'Form',
  9.     ),
  10.     'model' => array(
  11.         'path'      => 'models/',
  12.     ),
  13. ));

Finally, you can specify all of this when instantiating the object, by simply specifying a "resourceTypes" key in the options passed and a structure like that above:

  1. $resourceLoader = new Zend_Loader_Autoloader_Resource(array(
  2.     'basePath'      => 'path/to/some/directory',
  3.     'namespace'     => 'My',
  4.     'resourceTypes' => array(
  5.         'acl' => array(
  6.             'path'      => 'acls/',
  7.             'namespace' => 'Acl',
  8.         ),
  9.         'form' => array(
  10.             'path'      => 'forms/',
  11.             'namespace' => 'Form',
  12.         ),
  13.         'model' => array(
  14.             'path'      => 'models/',
  15.         ),
  16.     ),
  17. ));

The Module Resource Autoloader

Zend Framework ships with a concrete implementation of Zend_Loader_Autoloader_Resource that contains resource type mappings that cover the default recommended directory structure for Zend Framework MVC applications. This loader, Zend_Application_Module_Autoloader, comes with the following mappings:

  1. forms/       => Form
  2. models/      => Model
  3.     DbTable/ => Model_DbTable
  4.     mappers/ => Model_Mapper
  5. plugins/     => Plugin
  6. services/    => Service
  7. views/
  8.     helpers  => View_Helper
  9.     filters  => View_Filter

As an example, if you have a module with the prefix of "Blog_", and attempted to instantiate the class "Blog_Form_Entry", it would look in the resource directory's "forms/" subdirectory for a file named "Entry.php".

When using module bootstraps with Zend_Application, an instance of Zend_Application_Module_Autoloader will be created by default for each discrete module, allowing you to autoload module resources.

Using Resource Autoloaders as Object Factories

Resource Autoloader Reference

The Autoloader
Zend_Loader
Zend Framework手册 中文版
加载插件
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Loader
  • 动态加载文件和类
  • The Autoloader
  • Resource Autoloaders
  • 加载插件


加载插件 - Zend Framework Manual

Resource Autoloaders
Zend_Loader
Zend Framework手册 中文版
Zend_Locale

加载插件

很多 Zend Framework 组件支持插件，允许通过指定类的前缀和到类的文件（不需要在 include_path 或不需要遵循传统命名约定的文件）的路径动态加载函数。Zend_Loader_PluginLoader 提供了普通的函数来完成这个工作。

PluginLoader 的基本用法遵循 Zend Framework 的命名约定（一个文件一个类），解析路径时，使用下划线作为路径分隔符。当决定是否加载特别的插件类，允许传递可选的类前缀来预处理。另外，路径按 LIFO 顺序来搜索。由于 LIFO 搜索和类的前缀，允许命名空间给插件，这样可以从早期注册的路径来覆盖插件。

基本用例

首先，假定下面的目录结构和类文件，并且根（toplevel）目录和库目录在 include_path 中：

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');
?>

接着用类名中添加路径时定义的前缀后面的部分来加载一个给定的视图助手：

<?php
// load 'FormText' helper:
$formTextClass = $loader->load('FormText'); // 'Zend_View_Helper_FormText';

// load 'FormLabel' helper:
$formLabelClass = $loader->load('FormLabel'); // 'Foo_View_Helper_FormLabel'

// load 'FormSubmit' helper:
$formSubmitClass = $loader->load('FormSubmit'); // 'Bar_View_Helper_FormSubmit'
?>

类加载后，就可以实例化了。

Note: 为一个前缀注册多个路径
有时候，多个路径使用相同的前缀，Zend_Loader_PluginLoader 实际上为每个给定的前缀注册一个路径数组；最后注册的被首先检查，当你使用孵化器里的组件时，这相当有用。

Note: 实例化时定义路径
你可以提供给构造器一个可选的“前缀/路径”对（或“前缀/多个路径”）数组参数：

<?php
$loader = new Zend_Loader_PluginLoader(array(
    'Zend_View_Helper' => 'Zend/View/Helper/',
    'Foo_View_Helper'  => 'application/modules/foo/views/helpers',
    'Bar_View_Helper'  => 'application/modules/bar/views/helpers'
));
?>

Zend_Loader_PluginLoader 在不需要使用单态实例的情况下，也可选地允许共享插件，这是通过静态注册表来完成的，在实例化时需要注册表名作为构造器的第二个参数：

<?php
// Store plugins in static registry 'foobar':
$loader = new Zend_Loader_PluginLoader(array(), 'foobar');
?>

其它使用同名注册表来实例化 PluginLoader 的组件将可以访问已经加载的路径和插件。

处理插件路径

上节的例子示例如何给插件加载器添加路径，那么如何确定已经加载的路径或删除他们呢？

  • 如果没有提供 $prefix，getPaths($prefix = null) 以“前缀/路径”对返回所有的路径；或者如果提供了 $prefix，getPaths($prefix = null) 返回为给定的前缀注册的路径。

  • clearPaths($prefix = null) 将缺省地清除所有的已注册路径，或者如果提供了 $prefix 并放在堆栈里，只清除和那些和给定前缀关联的路径。

  • removePrefixPath($prefix, $path = null) 允许有选择地清除和给定前缀相关的特定的路径。如果没有提供 $path ，所有的和前缀相关的路径被清除，如果提供了 $path 并且相应的前缀存在，只有这个相关的路径被清除。

测试插件和获取类的名字

有时候你想确定在执行一个动作之前是否插件类已经加载，isLoaded() 返回插件名的状态。

PluginLoader 的另一个普通用例是确定已加载类的完全合格的插件类名，getClassName() 提供该功能。一般地，这个和 isLoaded() 联合使用：

<?php
if ($loader->isLoaded('Adapter')) {
    $class   = $loader->getClassName('Adapter');
    $adapter = call_user_func(array($class, 'getInstance'));
}
?>
Resource Autoloaders
Zend_Loader
Zend Framework手册 中文版
Zend_Locale
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Loader
  • 动态加载文件和类
  • The Autoloader
  • Resource Autoloaders
  • 加载插件


Zend_Locale - Zend Framework Manual

加载插件
Zend Framework Reference
Zend Framework手册 中文版
Introduction

Zend_Locale

Table of Contents
  • Introduction
  • Using Zend_Locale
  • Normalization and Localization
  • Working with Dates and Times
  • Supported locales
加载插件
Zend Framework Reference
Zend Framework手册 中文版
Introduction
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


Introduction - Zend Framework Manual

Zend_Locale
Zend_Locale
Zend Framework手册 中文版
Using Zend_Locale

Introduction

Zend_Locale is the Frameworks answer to the question, "How can the same application be used around the whole world?" Most people will say, "That's easy. Let's translate all our output to several languages." However, using simple translation tables to map phrases from one language to another is not sufficient. Different regions will have different conventions for first names, surnames, salutory titles, formatting of numbers, dates, times, currencies, etc.

We need » Localization and complementary » Internationalization . Both are often abbreviated to L10n and I18n. Internationalization refers more to support for use of systems, regardless of special needs unique to groups of users related by language, region, number format conventions, financial conventions, time and date conventions, etc. Localization involves adding explicit support to systems for special needs of these unique groups, such as language translation, and support for local customs or conventions for communicating plurals, dates, times, currencies, names, symbols, sorting and ordering, etc. L10n and I18n compliment each other. Zend Framework provides support for these through a combination of components, including Zend_Locale, Zend_Date, Zend_Measure, Zend_Translate, Zend_Currency, and Zend_TimeSync.

Tip

Zend_Locale and setLocale()

» PHP's documentation states that setlocale() is not threadsave because it is maintained per process and not per thread. This means that, in multithreaded environments, you can have the problem that the locale changes while the script never has changed the locale itself. This can lead to unexpected behaviour when you use setlocale() in your scripts.

When you are using Zend_Locale you will not have this limitations, because Zend_Locale is not related to or coupled with PHP's setlocale().

What is Localization

Localization means that an application (or homepage) can be used from different users which speak different languages. But as you already have expected Localization means more than only translating strings. It includes

  • Zend_Locale - Backend support of locales available for localization support within other Zend Framework components.

  • Zend_Translate - Translating of strings.

  • Zend_Date - Localization of dates, times.

  • Zend_Calendar - Localization of calendars (support for non-Gregorian calendar systems)

  • Zend_Currency - Localization of currencies.

  • Zend_Locale_Format - Parsing and generating localized numbers.

  • Zend_Locale_Data - Retrieve localized standard strings as country names, language names and » more from the CLDR .

  • TODO - Localization of collations

What is a Locale?

Each computer user makes use of Locales, even when they don't know it. Applications lacking localization support, normally have implicit support for one particular locale (the locale of the author). When a class or function makes use of localization, we say it is locale-aware. How does the code know which localization the user is expecting?

A locale string or object identifying a supported locale gives 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.

How are Locales Represented?

Locale identifiers consist of information about the user's language and preferred/primary geographic region (e.g. state or province of home or workplace). The locale identifier strings used in Zend Framework are internationally defined standard abbreviations of language and region, written as language_REGION. Both the language and region parts are abbreviated to alphabetic, ASCII characters.

Note: Be aware that there exist not only locales with 2 characters as most people think. Also there are languages and regions which are not only abbreviated with 2 characters. Therefor you should NOT strip the region and language yourself, but use Zend_Locale when you want to strip language or region from a locale string. Otherwise you could have unexpected behaviour within your code when you do this yourself.

A user from USA would expect the language English and the region USA, yielding the locale identifier "en_US". A user in Germany would expect the language German and the region Germany, yielding the locale identifier "de_DE". See the » list of pre-defined locale and region combinations, if you need to select a specific locale within Zend Framework.

Example #1 Choosing a specific locale

  1. $locale = new Zend_Locale('de_DE'); // German language _ Germany

A German user in America might expect the language German and the region USA, but these non-standard mixes are not supported directly as recognized "locales". Instead, if an invalid combination is used, then it will automatically be truncated by dropping the region code. For example, "de_IS" would be truncated to "de", and "xh_RU" would be truncated to "xh", because neither of these combinations are valid. Additionally, if the base language code is not supported (e.g. "zz_US") or does not exist, then a default "root" locale will be used. The "root" locale has default definitions for internationally recognized representations of dates, times, numbers, currencies, etc. The truncation process depends on the requested information, since some combinations of language and region might be valid for one type of data (e.g. dates), but not for another (e.g. currency format).

Beware of historical changes, as Zend Framework components do not know about or attempt to track the numerous timezone changes made over many years by many regions. For example, » we can see a historical list showing dozens of changes made by governments to when and if a particular region observes Daylight Savings Time, and even which timezone a particular geographic area belongs. Thus, when performing date math, the math performed by Zend Framework components will not adjust for these changes, but instead will give the correct time for the timezone using current, modern rules for DST and timezone assignment for geographic regions.

Selecting the Right Locale

For most situations, new Zend_Locale() will automatically select the correct locale, with preference given to information provided by the user's web browser. However, if new Zend_Locale(Zend_Locale::ENVIRONMENT) is used, then preference will be given to using the host server's environment configuration, as described below.

Example #2 Automatically selecting a locale

  1. $locale  = new Zend_Locale();
  2.
  3. // default behavior, same as above
  4. $locale1 = new Zend_Locale(Zend_Locale::BROWSER);
  5.
  6. // prefer settings on host server
  7. $locale2 = new Zend_Locale(Zend_Locale::ENVIRONMENT);
  8.
  9. // perfer framework app default settings
  10. $locale3 = new Zend_Locale(Zend_Locale::FRAMEWORK);

The search algorithm used by Zend_Locale for automatic selection of a locale uses three sources of information:

  1. const Zend_Locale::BROWSER - The user's Web browser provides information with each request, which is published by PHP in the global variable HTTP_ACCEPT_LANGUAGE. If no matching locale can be found, then preference is given to ENVIRONMENT and lastly FRAMEWORK.

  2. const Zend_Locale::ENVIRONMENT - PHP publishes the host server's locale via the PHP internal function setlocale(). If no matching locale can be found, then preference is given to FRAMEWORK and lastly BROWSER.

  3. const Zend_Locale::FRAMEWORK - When Zend Framework has a standardized way of specifying component defaults (planned, but not yet available), then using this constant during instantiation will give preference to choosing a locale based on these defaults. If no matching locale can be found, then preference is given to ENVIRONMENT and lastly BROWSER.

Usage of automatic Locales

Zend_Locale provides three additionally locales. These locales do not belong to any language or region. They are "automatic" locales which means that they have the same effect as the method getDefault() but without the negative effects like creating an instance. These "automatic" locales can be used anywhere, where also a standard locale and also the definition of a locale, its string representation, can be used. This offers simplicity for situations like working with locales which are provided by a browser.

There are three locales which have a slightly different behaviour:

  1. 'browser' - Zend_Locale should work with the information which is 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 his browser, Zend_Locale will use the first found locale. If the user does not provide a locale or the script is being called from the command line the automatic locale 'environment' will automatically be used and returned.

  2. 'environment' - Zend_Locale should work with the information which is provided by the host server. It is published by PHP via the internal function setlocale().

    If a environment provides more than one locale, Zend_Locale will use the first found locale. If the host does not provide a locale the automatic locale 'browser' will automatically be used and returned.

  3. 'auto' - Zend_Locale should automatically detect any locale which can be worked with. It will first search for a users locale and then, if not successful, search for the host locale.

    If no locale can be detected, it will throw an exception and tell you that the automatic detection has been failed.

Example #3 Using automatic locales

  1. // without automatic detection
  2. //$locale = new Zend_Locale(Zend_Locale::BROWSER);
  3. //$date = new Zend_Date($locale);
  4.
  5. // with automatic detection
  6. $date = new Zend_Date('auto');

Using a default Locale

In some environments it is not possible to detect a locale automatically. You can expect this behaviour when you get an request from command line or the requesting browser has no language tag set and additionally your server has the default locale 'C' set or another proprietary locale.

In such cases Zend_Locale will normally throw an exception with a message that the automatic detection of any locale was not successful. You have two options to handle such a situation. Either through setting a new locale per hand, or defining a default locale.

Example #4 Handling locale exceptions

  1. // within the bootstrap file
  2. try {
  3.     $locale = new Zend_Locale('auto');
  4. } catch (Zend_Locale_Exception $e) {
  5.     $locale = new Zend_Locale('de');
  6. }
  7.
  8. // within your model/controller
  9. $date = new Zend_Date($locale);

But this has one big negative effect. You will have to set your locale object within every class using Zend_Locale. This could become very unhandy if you are using multiple classes.

Since Zend Framework Release 1.5 there is a much better way to handle this. You can set a default locale which the static setDefault() method. Of course, every unknown or not full qualified locale will also throw an exception. setDefault() should be the first call before you initiate any class using Zend_Locale. See the following example for details:

Example #5 Setting a default locale

  1. // within the bootstrap file
  2. Zend_Locale::setDefault('de');
  3.
  4. // within your model/controller
  5. $date = new Zend_Date();

In the case that no locale can be detected, automatically the locale de will be used. Otherwise, the detected locale will be used.

ZF Locale-Aware Classes

In the Zend Framework, locale-aware classes rely on Zend_Locale to automatically select a locale, as explained above. For example, in a Zend Framework web application, constructing a date using Zend_Date without specifying a locale results in an object with a locale based on information provided by the current user's web browser.

Example #6 Dates default to correct locale of web users

  1. $date = new Zend_Date('2006',Zend_Date::YEAR);

To override this default behavior, and force locale-aware Zend Framework components to use specific locales, regardless of the origin of your website visitors, explicitly specify a locale as the third argument to the constructor.

Example #7 Overriding default locale selection

  1. $usLocale = new Zend_Locale('en_US');
  2. $date = new Zend_Date('2006', Zend_Date::YEAR, $usLocale);
  3. $temp = new Zend_Measure_Temperature('100,10',
  4.                                      Zend_Measure::TEMPERATURE,
  5.                                      $usLocale);

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.

Example #8 Performance optimization when using a default locale

  1. $locale = new Zend_Locale();
  2. $date = new Zend_Date('2006', Zend_Date::YEAR, $locale);
  3. $temp = new Zend_Measure_Temperature('100,10',
  4.                                      Zend_Measure::TEMPERATURE,
  5.                                      $locale);

Application wide locale

Zend Framework allows the usage of an application wide locale. You simply set an instance of Zend_Locale to the registry with the key 'Zend_Locale'. Then this instance will be used within all locale aware classes of Zend Framework. This way you set one locale within your registry and then you can forget about setting it again. It will automatically be used in all other classes. See the below example for the right usage:

Example #9 Usage of an application wide locale

  1. // within your bootstrap
  2. $locale = new Zend_Locale('de_AT');
  3. Zend_Registry::set('Zend_Locale', $locale);
  4.
  5. // within your model or controller
  6. $date = new Zend_Date();
  7. // print $date->getLocale();
  8. echo $date->getDate();

Zend_Locale_Format::setOptions(array $options)

The 'precision' option of a value is used to truncate or stretch extra digits. A value of '-1' disables modification of the number of digits in the fractional part of the value. The 'locale' option helps when parsing numbers and dates using separators and month names. The date format 'format_type' option selects between CLDR/ISO date format specifier tokens and PHP's date() tokens. The 'fix_date' option enables or disables heuristics that attempt to correct invalid dates. The 'number_format' option specifies a default number format for use with toNumber() (see Number localization ).

The 'date_format' option can be used to specify a default date format string, but beware of using getDate(), checkdateFormat() and getTime() after using setOptions() with a 'date_format'. To use these four methods with the default date format for a locale, use array('date_format' => null, 'locale' => $locale) for their options.

Example #10 Dates default to correct locale of web users

  1. Zend_Locale_Format::setOptions(array('locale' => 'en_US',
  2.                                      'fix_date' => true,
  3.                                      'format_type' => 'php'));

For working with the standard definitions of a locale the option Zend_Locale_Format::STANDARD can be used. Setting the option Zend_Locale_Format::STANDARD for date_format uses the standard definitions from the actual set locale. Setting it for number_format uses the standard number format for this locale. And setting it for locale uses the standard locale for this environment or browser.

Example #11 Using STANDARD definitions for setOptions()

  1. Zend_Locale_Format::setOptions(array('locale' => 'en_US',
  2.                                      'date_format' => 'dd.MMMM.YYYY'));
  3. // overriding the global set date format
  4. $date = Zend_Locale_Format::getDate('2007-04-20',
  5.                                     array('date_format' =>
  6.                                               Zend_Locale_Format::STANDARD);
  7.
  8. // global setting of the standard locale
  9. Zend_Locale_Format::setOptions(array('locale' => Zend_Locale_Format::STANDARD,
  10.                                      'date_format' => 'dd.MMMM.YYYY'));

Speed up Zend_Locale and its subclasses

Zend_Locale and its subclasses can be speed up by the usage of Zend_Cache. Use the static method Zend_Locale::setCache($cache) if you are using Zend_Locale. Zend_Locale_Format can be speed up the using the option cache within Zend_Locale_Format::setOptions(array('cache' => $adapter));. If you are using both classes you should only set the cache for Zend_Locale, otherwise the last set cache will overwrite the previous set cache. For convenience there are also the static methods getCache(), hasCache(), clearCache() and removeCache().

When no cache is set, then Zend_Locale will automatically set a cache itself. Sometimes it is wished to prevent that a cache is set, even if this degrades performance. In this case the static disableCache(true) method should be used. It does not only disable the actual set cache, without erasing it, but also prevents that a cache is automatically generated when no cache is set.

Zend_Locale
Zend_Locale
Zend Framework手册 中文版
Using Zend_Locale
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Locale
  • Introduction
  • Using Zend_Locale
  • Normalization and Localization
  • Working with Dates and Times
  • Supported locales


Using Zend_Locale - Zend Framework Manual

Introduction
Zend_Locale
Zend Framework手册 中文版
Normalization and Localization

Using Zend_Locale

Zend_Locale also provides localized information about locales for each locale, including localized names for other locales, days of the week, month names, etc.

Copying, Cloning, and Serializing Locale Objects

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().

Example #1 clone

  1. $locale = new Zend_Locale('ar');
  2.
  3. // Save the $locale object as a serialization
  4. $serializedLocale = $locale->serialize();
  5. // re-create the original object
  6. $localeObject = unserialize($serializedLocale);
  7.
  8. // Obtain a string identification of the locale
  9. $stringLocale = $locale->toString();
  10.
  11. // Make a cloned copy of the $local object
  12. $copiedLocale = clone $locale;
  13.
  14. print "copied: ", $copiedLocale->toString();
  15.
  16. // PHP automatically calls toString() via __toString()
  17. print "copied: ", $copiedLocale;

Equality

Zend_Locale also provides a convenience function to compare two locales. All locale-aware classes should provide a similar equality check.

Example #2 Check for equal locales

  1. $locale = new Zend_Locale();
  2. $mylocale = new Zend_Locale('en_US');
  3.
  4. // Check if locales are equal
  5. if ($locale->equals($mylocale)) {
  6.     print "Locales are equal";
  7. }

Default locales

The method 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 Zend Framework settings. As with the constructor for Zend_Locale, the first parameter selects a preference of which information to consider (BROWSER, ENVIRONMENT, or FRAMEWORK) first. 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, when available.

Example #3 Get default locales

  1. $locale = new Zend_Locale();
  2.
  3. // Return all default locales
  4. $found = $locale->getDefault();
  5. print_r($found);
  6.
  7. // Return only browser locales
  8. $found2 = $locale->getDefault(Zend_Locale::BROWSER,TRUE);
  9. print_r($found2);

To obtain only the default locales relevant to the BROWSER, ENVIRONMENT, or FRAMEWORK , use the corresponding method:

  • getEnvironment()

  • getBrowser()

  • getLocale()

Set a new locale

A new locale can be set with the function setLocale(). This function takes a locale string as parameter. If no locale is given, a locale is automatically selected. Since Zend_Locale objects are "light", this method exists primarily to cause side-effects for code that have references to the existing instance object.

Example #4 setLocale

  1. $locale = new Zend_Locale();
  2.
  3. // Actual locale
  4. print $locale->toString();
  5.
  6. // new locale
  7. $locale->setLocale('aa_DJ');
  8. print $locale->toString();

Getting the language and region

Use getLanguage() to obtain a string containing the two character language code from the string locale identifier. Use getRegion() to obtain a string containing the two character region code from the string locale identifier.

Example #5 getLanguage and getRegion

  1. $locale = new Zend_Locale();
  2.
  3. // if locale is 'de_AT' then 'de' will be returned as language
  4. print $locale->getLanguage();
  5.
  6. // if locale is 'de_AT' then 'AT' will be returned as region
  7. print $locale->getRegion();

Obtaining localized strings

getTranslationList() gives you access to localized informations of several types. These information are useful if you want to display localized data to a customer without the need of translating it. They are already available for your usage.

The requested list of information is always returned as named array. If you want to give more than one value to a explicit type where you wish to receive values from, you have to give an array instead of multiple values.

Example #6 getTranslationList

  1. $list = Zend_Locale::getTranslationList('language', 'de_AT');
  2.
  3. print_r ($list);
  4. // example key -> value pairs...
  5. // [de] -> Deutsch
  6. // [en] -> Englisch
  7.
  8. // use one of the returned key as value for the getTranslation() method
  9. // of another language
  10. print Zend_Locale::getTranslation('de', 'language', 'zh');
  11. // returns the translation for the language 'de' in chinese

You can receive this informations for all languages. But not all of the informations are completely available for all languages. Some of these types are also available through an own function for simplicity. See this list for detailed informations.

Details for getTranslationList($type = null, $locale = null, $value = null)
Type | Description
Language | Returns a localized list of all languages. The language part of the locale is returned as key and the translation as value
Script | Returns a localized list of all scripts. The script is returned as key and the translation as value
Territory | Returns a localized list of all territories. This contains countries, continents and territories. To get only territories and continents use '1' as value. To get only countries use '2' as value. The country part of the locale is used as key where applicable. In the other case the official ISO code for this territory is used. The translated territory is returned as value. When you omit the value you will get a list with both.
Variant | Returns a localized list of known variants of scripts. The variant is returned as key and the translation as value
Key | Returns a localized list of known keys. This keys are generic values used in translation. These are normally calendar, collation and currency. The key is returned as array key and the translation as value
Type | Returns a localized list of known types of keys. These are variants of types of calendar representations and types of collations. When you use 'collation' as value you will get all types of collations returned. When you use 'calendar' as value you will get all types of calendars returned. When you omit the value you will get a list all both returned. The type is used as key and the translation as value
Layout | Returns a list of rules which describes how to format special text parts
Characters | Returns a list of allowed characters within this locale
Delimiters | Returns a list of allowed quoting characters for this locale
Measurement | Returns a list of known measurement values. This list is depreciated
Months | Returns a list of all month representations within this locale. There are several different representations which are all returned as sub array. If you omit the value you will get a list of all months from the 'gregorian' calendar returned. You can give any known calendar as value to get a list of months from this calendar returned. Use Zend_Date for simplicity
Month | Returns a localized list of all month names for this locale. If you omit the value you will get the normally used gregorian full name of the months where each month number is used as key and the translated month is returned as value. You can get the months for different calendars and formats if you give an array as value. The first array entry has to be the calendar, the second the used context and the third the width to return. Use Zend_Date for simplicity
Days | Returns a list of all day representations within this locale. There are several different representations which are all returned as sub array. If you omit the value you will get a list of all days from the 'gregorian' calendar returned. You can give any known calendar as value to get a list of days from this calendar returned. Use Zend_Date for simplicity
Day | Returns a localized list of all day names for this locale. If you omit the value you will get the normally used gregorian full name of the days where the english day abbreviation is used as key and the translated day is returned as value. You can get the days for different calendars and formats if you give an array as value. The first array entry has to be the calendar, the second the used context and the third the width to return. Use Zend_Date for simplicity
Week | Returns a list of values used for proper week calculations within a locale. Use Zend_Date for simplicity
Quarters | Returns a list of all quarter representations within this locale. There are several different representations which are all returned as sub array. If you omit the value you will get a list of all quarters from the 'gregorian' calendar returned. You can give any known calendar as value to get a list of quarters from this calendar returned
Quarter | Returns a localized list of all quarter names for this locale. If you omit the value you will get the normally used gregorian full name of the quarters where each quarter number is used as key and the translated quarter is returned as value. You can get the quarters for different calendars and formats if you give an array as value. The first array entry has to be the calendar, the second the used context and the third the width to return
Eras | Returns a list of all era representations within this locale. If you omit the value you will get a list of all eras from the 'gregorian' calendar returned. You can give any known calendar as value to get a list of eras from this calendar returned
Era | Returns a localized list of all era names for this locale. If you omit the value you will get the normally used gregorian full name of the eras where each era number is used as key and the translated era is returned as value. You can get the eras for different calendars and formats if you give an array as value. The first array entry has to be the calendar and the second the width to return
Date | Returns a localized list of all date formats for this locale. The name of the dateformat is used as key and the format itself as value.If you omit the value you will get the date formats for the gregorian calendar returned. You can get the date formats for different calendars if you give the wished calendar as string. Use Zend_Date for simplicity
Time | Returns a localized list of all time formats for this locale. The name of the timeformat is used as key and the format itself as value. If you omit the value you will get the time formats for the gregorian calendar returned. You can get the time formats for different calendars if you give the wished calendar as string. Use Zend_Date for simplicity
DateTime | Returns a localized list of all known date-time formats for this locale. The name of the date-time format is used as key and the format itself as value. If you omit the value you will get the date-time formats for the gregorian calendar returned. You can get the date-time formats for different calendars if you give the wished calendar as string. Use Zend_Date for simplicity
DateItem | Returns a list of default formats for given date or time items
DateInterval | Returns a list of date or time formats which are used when you want to display intervals. The list is a multidimentional array where the first dimension is the interval format, and the second dimension is the token with the greatest difference.
Field | Returns a localized list of date fields which can be used to display calendars or date strings like 'month' or 'year' in a wished language. If you omit the value you will get this list for the gregorian calendar returned. You can get the list for different calendars if you give the wished calendar as string
Relative | Returns a localized list of relative dates which can be used to display textual relative dates like 'yesterday' or 'tomorrow' in a wished language. If you omit the value you will get this list for the gregorian calendar returned. You can get the list for different calendars if you give the wished calendar as string
Symbols | Returns a localized list of characters used for number representations
NameToCurrency | Returns a localized list of names for currencies. The currency is used as key and the translated name as value. Use Zend_Currency for simplicity
CurrencyToName | Returns a list of currencies for localized names. The translated name is used as key and the currency as value. Use Zend_Currency for simplicity
CurrencySymbol | Returns a list of known localized currency symbols for currencies. The currency is used as key and the symbol as value. Use Zend_Currency for simplicity
Question | Returns a list of localized strings for acceptance ('yes') and negotation ('no'). Use Zend_Locale's getQuestion method for simplicity
CurrencyFraction | Returns a list of fractions for currency values. The currency is used as key and the fraction as integer value. Use Zend_Currency for simplicity
CurrencyRounding | Returns a list of how to round which currency. The currency is used as key and the rounding as integer value. Use Zend_Currency for simplicity
CurrencyToRegion | Returns a list of currencies which are known to be used within a region. The ISO3166 value ('region') is used as array key and the ISO4217 value ('currency') as array value. Use Zend_Currency for simplicity
RegionToCurrency | Returns a list of regions where a currency is used . The ISO4217 value ('currency') is used as array key and the ISO3166 value ('region') as array value. When a currency is used in several regions these regions are separated with a whitespace. Use Zend_Currency for simplicity
RegionToTerritory | Returns a list of territories with the countries or sub territories which are included within that territory. The ISO territory code ('territory') is used as array key and the ISO3166 value ('region') as array value. When a territory contains several regions these regions are separated with a whitespace
TerritoryToRegion | Returns a list of regions and the territories where these regions are located. The ISO3166 code ('region') is used as array key and the ISO territory code ('territory') as array value. When a region is located in several territories these territories are separated with a whitespace
ScriptToLanguage | Returns a list of scripts which are used within a language. The language code is used as array key and the script code as array value. When a language contains several scripts these scripts are separated with a whitespace
LanguageToScript | Returns a list of languages which are using a script. The script code is used as array key and the language code as array value. When a script is used in several languages these languages are separated with a whitespace
TerritoryToLanguage | Returns a list of countries which are using a language. The country code is used as array key and the language code as array value. When a language is used in several countries these countries are separated with a whitespace
LanguageToTerritory | Returns a list of countries and the languages spoken within these countries. The country code is used as array key and the language code as array value. When a territory is using several languages these languages are separated with a whitespace
TimezoneToWindows | Returns a list of windows timezones and the related ISO timezone. The windows timezone is used as array key and the ISO timezone as array value
WindowsToTimezone | Returns a list of ISO timezones and the related windows timezone. The ISO timezone is used as array key and the windows timezone as array value
TerritoryToTimezone | Returns a list of regions or territories and the related ISO timezone. The ISO timezone is used as array key and the territory code as array value
TimezoneToTerritory | Returns a list of timezones and the related region or territory code. The region or territory code is used as array key and the ISO timezone as array value
CityToTimezone | Returns a localized list of cities which can be used as translation for a related timezone. Not for all timezones is a translation available, but for a user is the real city written in his languages more accurate than the ISO name of this timezone. The ISO timezone is used as array key and the translated city as array value
TimezoneToCity | Returns a list of timezones for localized city names. The localized city is used as array key and the ISO timezone name as array value
PhoneToTerritory | Returns a list of phone codes which are known to be used within a territory. The territory (region) is used as array key and the telephone code as array value
TerritoryToPhone | Returns a list of territories where a phone is used . The phone code is used as array key and the territory (region) as array value. When a phone code is used in several territories these territories are separated with a whitespace
NumericToTerritory | Returns a list of 3 digit number codes for territories. The territory (region) is used as array key and the 3 digit number code as array value
TerritoryToNumeric | Returns a list of territories with their 3 digit number code. The 3 digit number code is used as array key and the territory (region) as array value
Alpha3ToTerritory | Returns a list of 3 sign character codes for territories. The territory (region) is used as array key and the 3 sign character code as array value
TerritoryToAlpha3 | Returns a list of territories with their 3 sign character code. The 3 sign character code is used as array key and the territory (region) as array value
PostalToTerritory | Returns a list of territories with a regex for postal codes which are included within that territory. The ISO territory code ('territory') is used as array key and the regex as array value.
NumberingSystem | Returns a list of scripts with the notation for digits used within the script
FallbackToChar | Returns a list of replacement characters for often used unicode characters. This can be used to replace "©" with "(C)" for example
CharToFallback | Returns a list of unicode characters for often used replacement characters. This can be used to replace "(C)" with "©" for example
LocaleUpgrade | Returns a list of locale dependencies which can be used to upgrade a language to a full qualified locale
Unit | Returns a list of localized calendar units. This can be used to translate the strings "day", "month" and so on automatically

If you are in need of a single translated value, you can use the getTranslation() method. It returns always a string but it accepts some different types than the getTranslationList() method. Also value is the same as before with one difference. You have to give the detail you want to get returned as additional value.

Note: Because you have almost always give a value as detail this parameter has to be given as first parameter. This differs from the getTranslationList() method.

See the following table for detailed information:

Details for getTranslation($value = null, $type = null, $locale = null)
Type | Description
Language | Returns a translation for a language. To select the wished translation you must give the language code as value
Script | Returns a translation for a script. To select the wished translation you must give the script code as value
Territory or Country | Returns a translation for a territory. This can be countries, continents and territories. To select the wished variant you must give the territory code as value
Variant | Returns a translation for a script variant. To select the wished variant you must give the variant code as value
Key | Returns translation for a known keys. This keys are generic values used in translation. These are normally calendar, collation and currency. To select the wished key you must give the key code as value
DefaultCalendar | Returns the default calendar for the given locale. For most locales this will be 'gregorian'. Use Zend_Date for simplicity
MonthContext | Returns the default context for months which is used within the given calendar. If you omit the value the 'gregorian' calendar will be used. Use Zend_Date for simplicity
DefaultMonth | Returns the default format for months which is used within the given calendar. If you omit the value the 'gregorian' calendar will be used. Use Zend_Date for simplicity
Month | Returns a translation for a month. You have to give the number of the month as integer value. It has to be between 1 and 12. If you want to receive data for other calendars, contexts or formats, then you must give an array instead of an integer with the expected values. The array has to look like this: array( 'calendar', 'context', 'format', 'month number'). If you give only an integer then the default values are the 'gregorian' calendar, the context 'format' and the format 'wide'. Use Zend_Date for simplicity
DayContext | Returns the default context for ´days which is used within the given calendar. If you omit the value the 'gregorian' calendar will be used. Use Zend_Date for simplicity
DefaultDay | Returns the default format for days which is used within the given calendar. If you omit the value the 'gregorian' calendar will be used. Use Zend_Date for simplicity
Day | Returns a translation for a day. You have to give the english abbreviation of the day as string value ('sun', 'mon', etc.). If you want to receive data for other calendars, contexts or format, then you must give an array instead of an integer with the expected values. The array has to look like this: array('calendar', 'context', 'format', 'day abbreviation'). If you give only an string then the default values are the 'gregorian' calendar, the context 'format' and the format 'wide'. Use Zend_Date for simplicity
Quarter | Returns a translation for a quarter. You have to give the number of the quarter as integer and it has to be between 1 and 4. If you want to receive data for other calendars, contexts or formats, then you must give an array instead of an integer with the expected values. The array has to look like this: array('calendar', 'context', 'format', 'quarter number'). If you give only an string then the default values are the 'gregorian' calendar, the context 'format' and the format 'wide'
Am | Returns a translation for 'AM' in a expected locale. If you want to receive data for other calendars an string with the expected calendar. If you omit the value then the 'gregorian' calendar will be used. Use Zend_Date for simplicity
Pm | Returns a translation for 'PM' in a expected locale. If you want to receive data for other calendars an string with the expected calendar. If you omit the value then the 'gregorian' calendar will be used. Use Zend_Date for simplicity
Era | Returns a translation for an era within a locale. You have to give the era number as string or integer. If you want to receive data for other calendars or formats, then you must give an array instead of the era number with the expected values. The array has to look like this: array('calendar', 'format', 'era number'). If you give only an string then the default values are the 'gregorian' calendar and the 'abbr' format
DefaultDate | Returns the default date format which is used within the given calendar. If you omit the value the 'gregorian' calendar will be used. Use Zend_Date for simplicity
Date | Returns the date format for an given calendar or format within a locale. If you omit the value then the 'gregorian' calendar will be used with the 'medium' format. If you give a string then the 'gregorian' calendar will be used with the given format. Or you can also give an array which will have to look like this: array('calendar', 'format'). Use Zend_Date for simplicity
DefaultTime | Returns the default time format which is used within the given calendar. If you omit the value the 'gregorian' calendar will be used. Use Zend_Date for simplicity
Time | Returns the time format for an given calendar or format within a locale. If you omit the value then the 'gregorian' calendar will be used with the 'medium' format. If you give a string then the 'gregorian' calendar will be used with the given format. Or you can also give an array which will have to look like this: array('calendar', 'format'). Use Zend_Date for simplicity
DateTime | Returns the datetime format for the given locale which indicates how to display date with times in the same string within the given calendar. If you omit the value the 'gregorian' calendar will be used. Use Zend_Date for simplicity
DateItem | Returns the default format for a given date or time item
DateInterval | Returns the interval format for a given date or time format. The first value is the calendar format, normally 'gregorian'. The second value is the interval format and the third value the token with the greatest difference. For example: array('gregorian', 'yMMMM', 'y') returns the interval format for the date format 'yMMMM' where 'y' has the greatest difference.
Field | Returns a translated date field which can be used to display calendars or date strings like 'month' or 'year' in a wished language. You must give the field which has to be returned as string. In this case the 'gregorian' calendar will be used. You can get the field for other calendar formats if you give an array which has to look like this: array('calendar', 'date field')
Relative | Returns a translated date which is relative to today which can include date strings like 'yesterday' or 'tomorrow' in a wished language. You have to give the number of days relative to tomorrow to receive the expected string. Yesterday would be '-1', tomorrow '1' and so on. This will use the 'gregorian' calendar. If you want to get relative dates for other calendars you will have to give an array which has to look like this: array('calendar', 'relative days'). Use Zend_Date for simplicity
DecimalNumber | Returns the format for decimal numbers within a given locale. Use Zend_Locale_Format for simplicity
ScientificNumber | Returns the format for scientific numbers within a given locale
PercentNumber | Returns the format for percentage numbers within a given locale
CurrencyNumber | Returns the format for displaying currency numbers within a given locale. Use Zend_Currency for simplicity
NameToCurrency | Returns the translated name for a given currency. The currency has to be given in ISO format which is for example 'EUR' for the currency 'euro'. Use Zend_Currency for simplicity
CurrencyToName | Returns a currency for a given localized name. Use Zend_Currency for simplicity
CurrencySymbol | Returns the used symbol for a currency within a given locale. Not for all currencies exists a symbol. Use Zend_Currency for simplicity
Question | Returns a localized string for acceptance ('yes') and negotation ('no'). You have to give either 'yes' or 'no' as value to receive the expected string. Use Zend_Locale's getQuestion method for simplicity
CurrencyFraction | Returns the fraction to use for a given currency. You must give the currency as ISO value. Use Zend_Currency for simplicity
CurrencyRounding | Returns how to round a given currency. You must give the currency as ISO value. If you omit the currency then the 'DEFAULT' rounding will be returned. Use Zend_Currency for simplicity
CurrencyToRegion | Returns the currency for a given region. The region code has to be given as ISO3166 string for example 'AT' for austria. Use Zend_Currency for simplicity
RegionToCurrency | Returns the regions where a currency is used. The currency has to be given as ISO4217 code for example 'EUR' for euro. When a currency is used in multiple regions, these regions are separated with a whitespace character. Use Zend_Currency for simplicity
RegionToTerritory | Returns the regions for a given territory. The territory has to be given as ISO4217 string for example '001' for world. The regions within this territory are separated with a whitespace character
TerritoryToRegion | Returns the territories where a given region is located. The region has to be given in ISO3166 string for example 'AT' for austria. When a region is located in multiple territories then these territories are separated with a whitespace character
ScriptToLanguage | Returns the scripts which are used within a given language. The language has to be given as ISO language code for example 'en' for english. When multiple scripts are used within a language then these scripts are separated with a whitespace character
LanguageToScript | Returns the languages which are used within a given script. The script has to be given as ISO script code for example 'Latn' for latin. When a script is used in multiple languages then these languages are separated with a whitespace character
TerritoryToLanguage | Returns the territories where a given language is used. The language has to be given as ISO language code for example 'en' for english. When multiple territories exist where this language is used then these territories are separated with a whitespace character
LanguageToTerritory | Returns the languages which are used within a given territory. The territory has to be given as ISO3166 code for example 'IT' for italia. When a language is used in multiple territories then these territories are separated with a whitespace character
TimezoneToWindows | Returns a ISO timezone for a given windows timezone
WindowsToTimezone | Returns a windows timezone for a given ISO timezone
TerritoryToTimezone | Returns the territory for a given ISO timezone
TimezoneToTerritory | Returns the ISO timezone for a given territory
CityToTimezone | Returns the localized city for a given ISO timezone. Not for all timezones does a city translation exist
TimezoneToCity | Returns the ISO timezone for a given localized city name. Not for all cities does a timezone exist
PhoneToTerritory | Returns the telephone code for a given territory (region). The territory code has to be given as ISO3166 string for example 'AT' for austria
TerritoryToPhone | Returns the territory (region) where a telephone code is used. The telephone code has to be given as plain integer code for example '43' for +43. When a telephone code is used in multiple territories (regions), these territories are separated with a whitespace character
NumericToTerritory | Returns the 3 digit number code for a given territory (region). The territory code has to be given as ISO3166 string for example 'AT' for austria
TerritoryToNumeric | Returns the territory (region) for a 3 digit number code. The 3 digit number code has to be given as plain integer code for example '43'
Alpha3ToTerritory | Returns the 3 sign character code for a given territory (region). The territory code has to be given as ISO3166 string for example 'AT' for austria
TerritoryToAlpha3 | Returns the territory (region) for a 3 sign character code
PostalToTerritory | Returns the a regex for postal codes for a given territory. The territory has to be given as ISO4217 string for example '001' for world
NumberingSystem | Returns a scripts with the notation for digits used within this script
FallbackToChar | Returns a replacement character for a often used unicode character. This can be used to replace "©" with "(C)" for example
CharToFallback | Returns a unicode character for a often used replacement character. This can be used to replace "(C)" with "©" for example
LocaleUpgrade | Returns a locale dependencies for a given language which can be used to upgrade this language to a full qualified locale
Unit | Returns a localized calendar unit. This can be used to translate the strings "day", "month" and so on automatically. The first parameter has to be the type, and the second parameter has to be the count

Note: With Zend Framework 1.5 several old types have been renamed. This has to be done because of several new types, some misspelling and to increase the usability. See this table for a list of old to new types:

Differences between Zend Framework 1.0 and 1.5
Old type | New type
Country | Territory (with value '2')
Calendar | Type (with value 'calendar')
Month_Short | Month (with array('gregorian', 'format', 'abbreviated')
Month_Narrow | Month (with array('gregorian', 'stand-alone', 'narrow')
Month_Complete | Months
Day_Short | Day (with array('gregorian', 'format', 'abbreviated')
Day_Narrow | Day (with array('gregorian', 'stand-alone', 'narrow')
DateFormat | Date
TimeFormat | Time
Timezones | CityToTimezone
Currency | NameToCurrency
Currency_Sign | CurrencySymbol
Currency_Detail | CurrencyToRegion
Territory_Detail | TerritoryToRegion
Language_Detail | LanguageToTerritory

The example below demonstrates how to obtain the names of things in different languages.

Example #7 getTranslationList

  1. // prints the names of all countries in German language
  2. print_r(Zend_Locale::getTranslationList('country', 'de'));

The next example shows how to find the name of a language in another language, when the two letter iso country code is not known.

Example #8 Converting country name in one language to another

  1. $code2name = Zend_Locale::getLanguageTranslationList('en_US');
  2. $name2code = array_flip($code2name);
  3. $frenchCode = $name2code['French'];
  4. echo Zend_Locale::getLanguageTranslation($frenchCode, 'de_AT');
  5. // output is the German name of the French language

To generate a list of all languages known by Zend_Locale, with each language name shown in its own language, try the example below in a web page. Similarly, getCountryTranslationList() and getCountryTranslation() could be used to create a table mapping your native language names for regions to the names of the regions shown in another language. Use a try .. catch block to handle exceptions that occur when using a locale that does not exist. Not all languages are also locales. In the example, below exceptions are ignored to prevent early termination.

Example #9 All Languages written in their native language

  1. $list = Zend_Locale::getLanguageTranslationList('auto');
  2.
  3. foreach($list as $language => $content) {
  4.     try {
  5.         $output = Zend_Locale::getLanguageTranslation($language, $language);
  6.         if (is_string($output)) {
  7.             print "\n<br>[".$language."] ".$output;
  8.         }
  9.     } catch (Exception $e) {
  10.         continue;
  11.     }
  12. }

Obtaining translations for "yes" and "no"

Frequently, programs need to solicit a "yes" or "no" response from the user. Use getQuestion() to obtain an array containing the correct word(s) or regex strings to use for prompting the user in a particular $locale (defaults to the current object's locale). The returned array will contain the following informations :

  • yes and no: A generic string representation for yes and no responses. This will contain the first and most generic response from yesarray and noarray.

    yesarray and noarray: An array with all known yes and no responses. Several languages have more than just two responses. In general this is the full string and its abbreviation.

    yesexpr and noexpr: An generated regex which allows you to handle user response, and search for yes or no.

All of this informations are of course localized and depend on the set locale. See the following example for the informations you can receive:

Example #10 getQuestion()

  1. $locale = new Zend_Locale();
  2. // Question strings
  3. print_r($locale->getQuestion('de'));
  4.
  5. - - - Output - - -
  6.
  7. Array
  8. (
  9.     [yes] => ja
  10.     [no] => nein
  11.     [yesarray] => Array
  12.         (
  13.             [0] => ja
  14.             [1] => j
  15.         )
  16.
  17.     [noarray] => Array
  18.         (
  19.             [0] => nein
  20.             [1] => n
  21.         )
  22.
  23.     [yesexpr] => ^([jJ][aA]?)|([jJ]?)
  24.     [noexpr] => ^([nN]([eE][iI][nN])?)|([nN]?)
  25. )

Note: Until 1.0.3 yesabbr from the underlaying locale data was also available. Since 1.5 this information is no longer standalone available, but you will find the information from it within yesarray.

Get a list of all known locales

Sometimes you will want to get a list of all known locales. This can be used for several tasks like the creation of a selectbox. For this purpose you can use the static getLocaleList() method which will return a list of all known locales.

Example #11 getLocaleList()

  1. $localelist = Zend_Locale::getLocaleList();

Note: Note that the locales are returned as key of the array you will receive. The value is always a boolean TRUE.

Detecting locales

When you want to detect if a given input, regardless of its source, is a locale you should use the static isLocale() method. The first parameter of this method is the string which you want to check.

Example #12 Simple locale detection

  1. $input = 'to_RU';
  2. if (Zend_Locale::isLocale($input)) {
  3.     print "'{$input}' is a locale";
  4. } else {
  5.     print "Sorry... the given input is no locale";
  6. }

As you can see, the output of this method is always a boolean. There is only one reason you could get an exception when calling this method. When your system does not provide any locale and Zend Framework is not able to detect it automatically. Normally this shows that there is a problem with your OS in combination with PHP's setlocale().

You should also note that any given locale string will automatically be degraded if the region part does not exist for this locale. In our previous example the language 'to' does not exist in the region 'RU', but you will still get TRUE returned as Zend_Locale can work with the given input.

Still it's sometimes useful to prevent this automatic degrading, and this is where the second parameter of isLocale() comes in place. The strict parameter defaults to FALSE and can be used to prevent degrading when set to TRUE.

Example #13 Strict locale detection

  1. $input = 'to_RU';
  2. if (Zend_Locale::isLocale($input, true)) {
  3.     print "'{$input}' is a locale";
  4. } else {
  5.     print "Sorry... the given input is no locale";
  6. }

Now that you are able to detect if a given string is a locale you could add locale aware behaviour to your own classes. But you will soon detect that this will always leads to the same 15 lines of code. Something like the following example:

Example #14 Implement locale aware behaviour

  1. if ($locale === null) {
  2.     $locale = new Zend_Locale();
  3. }
  4.
  5. if (!Zend_Locale::isLocale($locale, true, false)) {
  6.     if (!Zend_Locale::isLocale($locale, false, false)) {
  7.         throw new Zend_Locale_Exception(
  8.             "The locale '$locale' is no known locale");
  9.     }
  10.
  11.     $locale = new Zend_Locale($locale);
  12. }
  13.
  14. if ($locale instanceof Zend_Locale) {
  15.     $locale = $locale->toString();
  16. }

With Zend Framework 1.8 we added a static findLocale() method which returns you a locale string which you can work with. It processes the following tasks:

  • Detects if a given string is a locale

  • Degrades the locale if it does not exist in the given region

  • Returns a previous set application wide locale if no input is given

  • Detects the locale from browser when the previous detections failed

  • Detects the locale from environment when the previous detections failed

  • Detects the locale from framework when the previous detections failed

  • Returns always a string which represents the found locale.

The following example shows how these checks and the above code can be simplified with one single call:

Example #15 Locale aware behaviour as with Zend Framework 1.8

  1. $locale = Zend_Locale::findLocale($inputstring);
Introduction
Zend_Locale
Zend Framework手册 中文版
Normalization and Localization
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Locale
  • Introduction
  • Using Zend_Locale
  • Normalization and Localization
  • Working with Dates and Times
  • Supported locales


Normalization and Localization - Zend Framework Manual

Using Zend_Locale
Zend_Locale
Zend Framework手册 中文版
Working with Dates and Times

Normalization and Localization

Zend_Locale_Format is a internal component used by Zend_Locale. All locale aware classes use Zend_Locale_Format for normalization and localization of numbers and dates. Normalization involves parsing input from a variety of data representations, like dates, into a standardized, structured representation, such as a PHP array with year, month, and day elements.

The exact same string containing a number or a date might mean different things to people with different customs and conventions. Disambiguation of numbers and dates requires rules about how to interpret these strings and normalize the values into a standardized data structure. Thus, all methods in Zend_Locale_Format require a locale in order to parse the input data.

Note: Default "root" Locale
 If no locale is specified, then normalization and localization will use the standard "root" locale, which might yield unexpected behavior, if the input originated in a different locale, or output for a specific locale was expected.

Number normalization: getNumber($input, Array $options)

There are many » number systems different from the common » decimal system (e.g. "3.14"). Numbers can be normalized with the getNumber() function to obtain the standard decimal representation. for all number-related discussions in this manual, » Arabic/European numerals (0,1,2,3,4,5,6,7,8,9) are implied, unless explicitly stated otherwise. The options array may contain a 'locale' to define grouping and decimal characters. The array may also have a 'precision' to truncate excess digits from the result.

Example #1 Number normalization

  1. $locale = new Zend_Locale('de_AT');
  2. $number = Zend_Locale_Format::getNumber('13.524,678',
  3.                                         array('locale' => $locale,
  4.                                               'precision' => 3)
  5.                                        );
  6.
  7. print $number; // will return 13524.678

Precision and Calculations

Since getNumber($value, array $options = array()) can normalize extremely large numbers, check the result carefully before using finite precision calculations, such as ordinary PHP math operations. For example, if ((string)int_val($number) != $number) { use » BCMath or » GMP . Most PHP installations support the BCMath extension.

Also, the precision of the resulting decimal representation can be rounded to a desired length with getNumber() with the option 'precision'. If no precision is given, no rounding occurs. Use only PHP integers to specify the precision.

If the resulting decimal representation should be truncated to a desired length instead of rounded the option 'number_format' can be used instead. Define the length of the decimal representation with the desired length of zeros. The result will then not be rounded. So if the defined precision within number_format is zero the value "1.6" will return "1", not "2. See the example nearby:

Example #2 Number normalization with precision

  1. $locale = new Zend_Locale('de_AT');
  2. $number = Zend_Locale_Format::getNumber('13.524,678',
  3.                                         array('precision' => 1,
  4.                                               'locale' => $locale)
  5.                                        );
  6. print $number; // will return 13524.7
  7.
  8. $number = Zend_Locale_Format::getNumber('13.524,678',
  9.                                         array('number_format' => '#.00',
  10.                                               'locale' => $locale)
  11.                                        );
  12. print $number; // will return 13524.67

Number localization

toNumber($value, array $options = array()) can localize numbers to the following supported locales . This function will return a localized string of the given number in a conventional format for a specific locale. The 'number_format' option explicitly specifies a non-default number format for use with toNumber().

Example #3 Number localization

  1. $locale = new Zend_Locale('de_AT');
  2. $number = Zend_Locale_Format::toNumber(13547.36,
  3.                                        array('locale' => $locale));
  4.
  5. // will return 13.547,36
  6. print $number;

Note: Unlimited length
 toNumber() can localize numbers with unlimited length. It is not related to integer or float limitations.

The same way as within getNumber(), toNumber() handles precision. If no precision is given, the complete localized number will be returned.

Example #4 Number localization with precision

  1. $locale = new Zend_Locale('de_AT');
  2. $number = Zend_Locale_Format::toNumber(13547.3678,
  3.                                        array('precision' => 2,
  4.                                              'locale' => $locale));
  5.
  6. // will return 13.547,37
  7. print $number;

Using the option 'number_format' a self defined format for generating a number can be defined. The format itself has to be given in CLDR format as described below. The locale is used to get separation, precision and other number formatting signs from it. German for example defines ',' as precision separation and in English the '.' sign is used.

Format tokens for self generated number formats
Token | Description | Example format | Generated output
#0 | Generates a number without precision and separation | #0 | 1234567
, | Generates a separation with the length from separation to next separation or to 0 | #,##0 | 1,234,567
#,##,##0 | Generates a standard separation of 3 and all following separations with 2 | #,##,##0 | 12,34,567
. | Generates a precision | #0.# | 1234567.1234
0 | Generates a precision with a defined length | #0.00 | 1234567.12

Example #5 Using a self defined number format

  1. $locale = new Zend_Locale('de_AT');
  2. $number = Zend_Locale_Format::toNumber(13547.3678,
  3.                                        array('number_format' => '#,#0.00',
  4.                                              'locale' => 'de')
  5.                                       );
  6.
  7. // will return 1.35.47,36
  8. print $number;
  9.
  10. $number = Zend_Locale_Format::toNumber(13547.3,
  11.                                        array('number_format' => '#,##0.00',
  12.                                              'locale' => 'de')
  13.                                        );
  14.
  15. // will return 13.547,30
  16. print $number;

Number testing

isNumber($value, array $options = array()) checks if a given string is a number and returns TRUE or FALSE.

Example #6 Number testing

  1. $locale = new Zend_Locale();
  2. if (Zend_Locale_Format::isNumber('13.445,36', array('locale' => 'de_AT')) {
  3.     print "Number";
  4. } else {
  5.     print "not a Number";
  6. }

Float value normalization

Floating point values can be parsed with the getFloat($value, array $options = array()) function. A floating point value will be returned.

Example #7 Floating point value normalization

  1. $locale = new Zend_Locale('de_AT');
  2. $number = Zend_Locale_Format::getFloat('13.524,678',
  3.                                        array('precision' => 2,
  4.                                              'locale' => $locale)
  5.                                       );
  6.
  7. // will return 13524.68
  8. print $number;

Floating point value localization

toFloat() can localize floating point values. This function will return a localized string of the given number.

Example #8 Floating point value localization

  1. $locale = new Zend_Locale('de_AT');
  2. $number = Zend_Locale_Format::toFloat(13547.3655,
  3.                                       array('precision' => 1,
  4.                                             'locale' => $locale)
  5.                                      );
  6.
  7. // will return 13.547,4
  8. print $number;

Floating point value testing

isFloat($value, array $options = array()) checks if a given string is a floating point value and returns TRUE or FALSE.

Example #9 Floating point value testing

  1. $locale = new Zend_Locale('de_AT');
  2. if (Zend_Locale_Format::isFloat('13.445,36', array('locale' => $locale)) {
  3.     print "float";
  4. } else {
  5.     print "not a float";
  6. }

Integer value normalization

Integer values can be parsed with the getInteger() function. A integer value will be returned.

Example #10 Integer value normalization

  1. $locale = new Zend_Locale('de_AT');
  2. $number = Zend_Locale_Format::getInteger('13.524,678',
  3.                                          array('locale' => $locale));
  4.
  5. // will return 13524
  6. print $number;

Integer point value localization

toInteger($value, array $options = array()) can localize integer values. This function will return a localized string of the given number.

Example #11 Integer value localization

  1. $locale = new Zend_Locale('de_AT');
  2. $number = Zend_Locale_Format::toInteger(13547.3655,
  3.                                         array('locale' => $locale));
  4.
  5. // will return 13.547
  6. print $number;

Integer value testing

isInteger($value, array $options = array()) checks if a given string is a integer value and returns TRUE or FALSE.

Example #12 Integer value testing

  1. $locale = new Zend_Locale('de_AT');
  2. if (Zend_Locale_Format::isInteger('13.445', array('locale' => $locale)) {
  3.     print "integer";
  4. } else {
  5.     print "not a integer";
  6. }

Numeral System Conversion

Zend_Locale_Format::convertNumerals() converts digits between different » numeral systems , including the standard Arabic/European/Latin numeral system (0,1,2,3,4,5,6,7,8,9), not to be confused with » Eastern Arabic numerals sometimes used with the Arabic language to express numerals. Attempts to use an unsupported numeral system will result in an exception, to avoid accidentally performing an incorrect conversion due to a spelling error. All characters in the input, which are not numerals for the selected numeral system, are copied to the output with no conversion provided for unit separator characters. Zend_Locale* components rely on the data provided by CLDR (see their » list of scripts grouped by language).

In CLDR and hereafter, the Europena/Latin numerals will be referred to as "Latin" or by the assigned 4-letter code "Latn". Also, the CLDR refers to this numeral systems as "scripts".

Suppose a web form collected a numeric input expressed using Eastern Arabic digits "١‎٠٠". Most software and PHP functions expect input using Arabic numerals. Fortunately, converting this input to its equivalent Latin numerals "100" requires little effort using convertNumerals($inputNumeralString, $sourceNumeralSystem, $destNumeralSystem) , which returns the $input with numerals in the script $sourceNumeralSystem converted to the script $destNumeralSystem.

Example #13 Converting numerals from Eastern Arabic scripts to European/Latin scripts

  1. $arabicScript = "١‎٠٠";   // Arabic for "100" (one hundred)
  2. $latinScript = Zend_Locale_Format::convertNumerals($arabicScript,
  3.                                                    'Arab',
  4.                                                    'Latn');
  5.
  6. print "\nOriginal:   " . $arabicScript;
  7. print "\nNormalized: " . $latinScript;

Similarly, any of the supported numeral systems may be converted to any other supported numeral system.

Example #14 Converting numerals from Latin script to Eastern Arabic script

  1. $latinScript = '123';
  2. $arabicScript = Zend_Locale_Format::convertNumerals($latinScript,
  3.                                                     'Latn',
  4.                                                     'Arab');
  5.
  6. print "\nOriginal:  " . $latinScript;
  7. print "\nLocalized: " . $arabicScript;

Example #15 Getting 4 letter CLDR script code using a native-language name of the script

  1. function getScriptCode($scriptName, $locale)
  2. {
  3.     $scripts2names = Zend_Locale_Data::getList($locale, 'script');
  4.     $names2scripts = array_flip($scripts2names);
  5.     return $names2scripts[$scriptName];
  6. }
  7. echo getScriptCode('Latin', 'en'); // outputs "Latn"
  8. echo getScriptCode('Tamil', 'en'); // outputs "Taml"
  9. echo getScriptCode('tamoul', 'fr'); // outputs "Taml"

For a list of supported numeral systems call Zend_Locale::getTranslationList('numberingsystem', 'en').

Using Zend_Locale
Zend_Locale
Zend Framework手册 中文版
Working with Dates and Times
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Locale
  • Introduction
  • Using Zend_Locale
  • Normalization and Localization
  • Working with Dates and Times
  • Supported locales


Working with Dates and Times - Zend Framework Manual

Normalization and Localization
Zend_Locale
Zend Framework手册 中文版
Supported locales

Working with Dates and Times

Zend_Locale_Format provides several methods for working with dates and times to help convert and normalize between different formats for different locales. Use Zend_Date for manipulating dates, and working with date strings that already conform to one of the many internationally recognized standard formats, or one of the localized date formats supported by Zend_Date . Using an existing, pre-defined format offers advantages, including the use of well-tested code, and the assurance of some degree of portability and interoperability (depending on the standard used). The examples below do not follow these recommendations, since using non-standard date formats would needlessly increase the difficulty of understanding these examples.

Normalizing Dates and Times

The getDate() method parses strings containing dates in localized formats. The results are returned in a structured array, with well-defined keys for each part of the date. In addition, the array will contain a key 'date_format' showing the format string used to parse the input date string. Since a localized date string may not contain all parts of a date/time, the key-value pairs are optional. For example, if only the year, month, and day is given, then all time values are suppressed from the returned array, and vice-versa if only hour, minute, and second were given as input. If no date or time can be found within the given input, an exception will be thrown.

If setOption(array('fix_date' => true)) is set the getDate() method adds a key 'fixed' with a whole number value indicating if the input date string required "fixing" by rearranging the day, month, or year in the input to fit the format used.

Key values for getDate() with option 'fix_date'
value | meaning
0 | nothing to fix
1 | fixed false month
2 | swapped day and year
3 | swapped month and year
4 | swapped month and day

For those needing to specify explicitly the format of the date string, the following format token specifiers are supported. If an invalid format specifier is used, such as the PHP 'i' specifier when in ISO format mode, then an error will be thrown by the methods in Zend_Locale_Format that support user-defined formats.

These specifiers (below) are a small subset of the full "ISO" set supported by Zend_Date's toString(). If you need to use PHP date() compatible format specifiers, then first call setOptions(array('format_type' => 'php')). And if you want to convert only one special format string from PHP date() compatible format to "ISO" format use convertPhpToIsoFormat(). Currently, the only practical difference relates to the specifier for minutes ('m' using the ISO default, and 'i' using the PHP date format).

Return values
getDate() format character | Array key | Returned value | Minimum | Maximum
d | day | integer | 1 | 31
M | month | integer | 1 | 12
y | year | integer | no limit | PHP integer's maximum
h | hour | integer | 0 | PHP integer's maximum
m | minute | integer | 0 | PHP integer's maximum
s | second | integer | 0 | PHP integer's maximum

Example #1 Normalizing a date

  1. $dateString = Zend_Locale_Format::getDate('13.04.2006',
  2.                                           array('date_format' =>
  3.                                                     'dd.MM.yyyy')
  4.                                          );
  5.
  6. // creates a Zend_Date object for this date
  7. $dateObject = Zend_Date('13.04.2006',
  8.                          array('date_format' => 'dd.MM.yyyy'));
  9.
  10. print_r($dateString); // outputs:
  11.
  12. Array
  13. (
  14.     [format] => dd.MM.yyyy
  15.     [day] => 13
  16.     [month] => 4
  17.     [year] => 2006
  18. )
  19.
  20. // alternatively, some types of problems with input data can be
  21. // automatically corrected
  22. $date = Zend_Locale_Format::getDate('04.13.2006',
  23.                                     array('date_format' => 'dd.MM.yyyy',
  24.                                           'fix_date' => true)
  25.                                    );
  26.
  27. print_r($date); // outputs:
  28.
  29. Array
  30. (
  31.     [format] => dd.MM.yyyy
  32.     [day] => 13
  33.     [month] => 4
  34.     [year] => 2006
  35.     [fixed] => 4
  36. )

Since getDate() is "locale-aware", specifying the $locale is sufficient for date strings adhering to that locale's format. The option 'fix_date' uses simple tests to determine if the day or month is not valid, and then applies heuristics to try and correct any detected problems. Note the use of 'Zend_Locale_Format::STANDARD' as the value for 'date_format' to prevent the use of a class-wide default date format set using setOptions(). This forces getDate to use the default date format for $locale.

Example #2 Normalizing a date by locale

  1. $locale = new Zend_Locale('de_AT');
  2. $date = Zend_Locale_Format::getDate('13.04.2006',
  3.                                     array('date_format' =>
  4.                                               Zend_Locale_Format::STANDARD,
  5.                                           'locale' => $locale)
  6.                                    );
  7.
  8. print_r ($date);

A complete date and time is returned when the input contains both a date and time in the expected format.

Example #3 Normalizing a date with time

  1. $locale = new Zend_Locale('de_AT');
  2. $date = Zend_Locale_Format::getDate('13.04.2005 22:14:55',
  3.                                     array('date_format' =>
  4.                                                 Zend_Locale_Format::STANDARD,
  5.                                           'locale' => $locale)
  6.                                     );
  7.
  8. print_r ($date);

If a specific format is desired, specify the $format argument, without giving a $locale. Only single-letter codes (H, m, s, y, M, d), and MMMM and EEEE are supported in the $format.

Example #4 Normalizing a userdefined date

  1. $date = Zend_Locale_Format::getDate('13200504T551422',
  2.                                     array('date_format' =>
  3.                                               'ddyyyyMM ssmmHH')
  4.                                    );
  5.
  6. print_r ($date);

The format can include the following signs :

Format definition
Format Letter | Description
d or dd | 1 or 2 digit day
M or MM | 1 or 2 digit month
y or yy | 1 or 2 digit year
yyyy | 4 digit year
h | 1 or 2 digit hour
m | 1 or 2 digit minute
s | 1 or 2 digit second

Examples for proper formats are

Example formats
Formats | Input | Output
dd.MM.yy | 1.4.6 | ['day'] => 1, ['month'] => 4, ['year'] => 6
dd.MM.yy | 01.04.2006 | ['day'] => 1, ['month'] => 4, ['year'] => 2006
yyyyMMdd | 1.4.6 | ['day'] => 6, ['month'] => 4, ['year'] => 1

Note: Database date format
 To parse a database date value (f.e. MySql or MsSql), use Zend_Date's ISO_8601 format instead of getDate().

The option 'fix_date' uses simple tests to determine if the day or month is not valid, and then applies heuristics to try and correct any detected problems. getDate() automatically detects and corrects some kinds of problems with input, such as misplacing the year:

Example #5 Automatic correction of input dates

  1. $date = Zend_Locale_Format::getDate('41.10.20',
  2.                                     array('date_format' => 'ddMMyy',
  3.                                           'fix_date' => true)
  4.                                    );
  5.
  6. // instead of 41 for the day, the 41 will be returned as year value
  7. print_r ($date);

Testing Dates

Use checkDateFormat($inputString, array('date_format' => $format, $locale)) to check if a given string contains all expected date parts. The checkDateFormat() method uses getDate(), but without the option 'fixdate' to avoid returning TRUE when the input fails to conform to the date format. If errors are detected in the input, such as swapped values for months and days, the option 'fixdate' method will apply heuristics to "correct" dates before determining their validity.

Example #6 Date testing

  1. $locale = new Zend_Locale('de_AT');
  2. // using the default date format for 'de_AT', is this a valid date?
  3. if (Zend_Locale_Format::checkDateFormat('13.Apr.2006',
  4.                                         array('date_format' =>
  5.                                                   Zend_Locale_Format::STANDARD,
  6.                                               $locale)
  7.                                        ) {
  8.     print "date";
  9. } else {
  10.     print "not a date";
  11. }

Normalizing a Time

Normally, a time will be returned with a date, if the input contains both. If the proper format is not known, but the locale relevant to the user input is known, then getTime() should be used, because it uses the default time format for the selected locale.

Example #7 Normalize an unknown time

  1. $locale = new Zend_Locale('de_AT');
  2. if (Zend_Locale_Format::getTime('13:44:42',
  3.                                 array('date_format' =>
  4.                                           Zend_Locale_Format::STANDARD,
  5.                                       'locale' => $locale)) {
  6.     print "time";
  7. } else {
  8.     print "not a time";
  9. }

Testing Times

Use checkDateFormat() to check if a given string contains a proper time. The usage is exact the same as with checking Dates, only date_format should contain the parts which you expect to have.

Example #8 Testing a time

  1. $locale = new Zend_Locale('de_AT');
  2. if (Zend_Locale_Format::checkDateFormat('13:44:42',
  3.                                         array('date_format' => 'HH:mm:ss',
  4.                                               'locale' => $locale)) {
  5.     print "time";
  6. } else {
  7.     print "not a time";
  8. }
Normalization and Localization
Zend_Locale
Zend Framework手册 中文版
Supported locales
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Locale
  • Introduction
  • Using Zend_Locale
  • Normalization and Localization
  • Working with Dates and Times
  • Supported locales


Supported locales - Zend Framework Manual

Working with Dates and Times
Zend_Locale
Zend Framework手册 中文版
Zend_Log

Supported locales

Zend_Locale provides information on several locales. The following table shows all languages and their related locales, sorted by language:

List of all supported languages
Language | Locale | Region
Afar | aa | ---
 | aa_DJ | Djibouti
 | aa_ER | Eritrea
 | aa_ET | Ethiopia
Afrikaans | af | ---
 | af_NA | Namibia
 | af_ZA | South Africa
Akan | ak | ---
 | ak_GH | Ghana
Amharic | am | ---
 | am_ET | Ethiopia
Arabic | ar | ---
 | ar_AE | United Arab Emirates
 | ar_BH | Bahrain
 | ar_DZ | Algeria
 | ar_EG | Egypt
 | ar_IQ | Iraq
 | ar_JO | Jordan
 | ar_KW | Kuwait
 | ar_LB | Lebanon
 | ar_LY | Libya
 | ar_MA | Morocco
 | ar_OM | Oman
 | ar_QA | Qatar
 | ar_SA | Saudi Arabia
 | ar_SD | Sudan
 | ar_SY | Syria
 | ar_TN | Tunisia
 | ar_YE | Yemen
Assamese | as | ---
 | as_IN | India
Azerbaijani | az | ---
 | az_AZ | Azerbaijan
Belarusian | be | ---
 | be_BY | Belarus
Bulgarian | bg | ---
 | bg_BG | Bulgaria
Bengali | bn | ---
 | bn_BD | Bangladesh
 | bn_IN | India
Tibetan | bo | ---
 | bo_CN | China
 | bn_IN | India
Bosnian | bs | ---
 | bs_BA | Bosnia and Herzegovina
Blin | byn | ---
 | byn_ER | Eritrea
Catalan | ca | ---
 | ca_ES | Spain
Atsam | cch | ---
 | cch_NG | Nigeria
Coptic | cop | ---
Czech | cs | ---
 | cs_CZ | Czech Republic
Welsh | cy | ---
 | cy_GB | United Kingdom
Danish | da | ---
 | da_DK | Denmark
German | de | ---
 | de_AT | Austria
 | de_BE | Belgium
 | de_CH | Switzerland
 | de_DE | Germany
 | de_LI | Liechtenstein
 | de_LU | Luxembourg
Divehi | dv | ---
 | dv_MV | Maldives
Dzongkha | dz | ---
 | dz_BT | Bhutan
Ewe | ee | ---
 | ee_GH | Ghana
 | ee_TG | Togo
Greek | el | ---
 | el_CY | Cyprus
 | el_GR | Greece
English | en | ---
 | en_AS | American Samoa
 | en_AU | Australia
 | en_BE | Belgium
 | en_BW | Botswana
 | en_BZ | Belize
 | en_CA | Canada
 | en_GB | United Kingdom
 | en_GU | Guam
 | en_HK | Hong Kong
 | en_IE | Ireland
 | en_IN | India
 | en_JM | Jamaica
 | en_MH | Marshall Islands
 | en_MP | Northern Mariana Islands
 | en_MT | Malta
 | en_NA | Namibia
 | en_NZ | New Zealand
 | en_PH | Philippines
 | en_PK | Pakistan
 | en_SG | Singapore
 | en_TT | Trinidad and Tobago
 | en_UM | United States Minor Outlying Islands
 | en_US | United States
 | en_VI | U.S. Virgin Islands
 | en_ZA | South Africa
 | en_ZW | Zimbabwe
Esperanto | eo | ---
Spanish | es | ---
 | es_AR | Argentina
 | es_BO | Bolivia
 | es_CL | Chile
 | es_CO | Colombia
 | es_CR | Costa Rica
 | es_DO | Dominican Republic
 | es_EC | Ecuador
 | es_ES | Spain
 | es_GT | Guatemala
 | es_HN | Honduras
 | es_MX | Mexico
 | es_NI | Nicaragua
 | es_PA | Panama
 | es_PE | Peru
 | es_PR | Puerto Rico
 | es_PY | Paraguay
 | es_SV | El Salvador
 | es_US | United States
 | es_UY | Uruguay
 | es_VE | Venezuela
Estonian | et | ---
 | et_EE | Estonia
Basque | eu | ---
 | eu_ES | Spain
Persian | fa | ---
 | fa_AF | Afghanistan
 | fa_IR | Iran
Finnish | fi | ---
 | fi_FI | Finland
Filipino | fil | ---
 | fil_PH | Philippines
Faroese | fo | ---
 | fo_FO | Faroe Islands
French | fr | ---
 | fr_BE | Belgium
 | fr_CA | Canada
 | fr_CH | Switzerland
 | fr_FR | France
 | fr_LU | Luxembourg
 | fr_MC | Monaco
 | fr_SN | Senegal
Friulian | fur | ---
 | fur_IT | Italy
Irish | ga | ---
 | ga_IE | Ireland
Ga | gaa | ---
 | gaa_GH | Ghana
Geez | gez | ---
 | gez_ER | Eritrea
 | gez_ET | Ethiopia
Gallegan | gl | ---
 | gl_ES | Spain
Swiss German | gsw | ---
 | gsw_CH | Swiss
Gujarati | gu | ---
 | gu_IN | India
Manx | gv | ---
 | gv_GB | United Kingdom
Hausa | ha | ---
 | ha_GH | Ghana
 | ha_NE | Niger
 | ha_NG | Nigeria
 | ha_SD | Sudan
Hawaiian | haw | ---
 | haw_US | United States
Hebrew | he | ---
 | he_IL | Israel
Hindi | hi | ---
 | hi_IN | India
Croatian | hr | ---
 | hr_HR | Croatia
Hungarian | hu | ---
 | hu_HU | Hungary
Armenian | hy | ---
Interlingua | ia | ---
Indonesian | id | ---
 | id_ID | Indonesia
Igbo | ig | ---
 | ig_NG | Nigeria
Sichuan Yi | ii | ---
 | ii_CN | China
Indonesian | in | ---
Icelandic | is | ---
 | is_IS | Iceland
Italian | it | ---
 | it_CH | Switzerland
 | it_IT | Italy
Inuktitut | iu | ---
Hebrew | iw | ---
Japanese | ja | ---
 | ja_JP | Japan
Georgian | ka | ---
 | ka_GE | Georgia
Jju | kaj | ---
 | kaj_NG | Nigeria
Kamba | kam | ---
 | kam_KE | Kenya
Tyap | kcg | ---
 | kcg_NG | Nigeria
Koro | kfo | ---
 | kfo_CI | Ivory Coast
Kazakh | kk | ---
 | kk_KZ | Kazakhstan
Kalaallisut | kl | ---
 | kl_GL | Greenland
Khmer | km | ---
 | km_KH | Cambodia
Kannada | kn | ---
 | kn_IN | India
Korean | ko | ---
 | ko_KR | South Korea
Konkani | kok | ---
 | kok_IN | India
Kpelle | kpe | ---
 | kpe_GN | Guinea
 | kpe_LR | Liberia
Kurdish | ku | ---
 | ku_IQ | Iraq
ku_IR | Iran
ku_SY | Syria
ku_TR | Turkey
Cornish | kw | ---
 | kw_GB | United Kingdom
Kirghiz | ky | ---
 | ky_KG | Kyrgyzstan
Lingala | ln | ---
 | ln_CD | Congo - Kinshasa
 | ln_CG | Congo - Brazzaville
Lao | lo | ---
 | lo_LA | Laos
Lithuanian | lt | ---
 | lt_LT | Lithuania
Latvian | lv | ---
 | lv_LV | Latvia
Macedonian | mk | ---
 | mk_MK | Macedonia
Malayalam | ml | ---
 | ml_IN | India
Mongolian | mn | ---
 | mn_CN | China
 | mn_MN | Mongolia
Romanian | mo | ---
Marathi | mr | ---
 | mr_IN | India
Malay | ms | ---
 | ms_BN | Brunei
 | ms_MY | Malaysia
Maltese | mt | ---
 | mt_MT | Malta
Burmese | my | ---
 | my_MM | Myanmar
Norwegian Bokmal | nb | ---
 | nb_NO | Norway
Low German | nds | ---
 | nds_DE | Germany
Nepali | ne | ---
 | ne_IN | India
 | ne_NP | Nepal
Dutch | nl | ---
 | nl_BE | Belgium
 | nl_NL | Netherlands
Norwegian Nynorsk | nn | ---
 | nn_NO | Norway
Norwegian | no | ---
South Ndebele | nr | ---
 | nr_ZA | South Africa
Northern Sotho | nso | ---
 | nso_ZA | South Africa
Nyanja | ny | ---
 | ny_MW | Malawi
Occitan | oc | ---
 | oc_FR | France
Oromo | om | ---
 | om_ET | Ethiopia
 | om_KE | Kenya
Oriya | or | ---
 | or_IN | India
Punjabi | pa | ---
 | pa_IN | India
 | pa_PK | Pakistan
Polish | pl | ---
 | pl_PL | Poland
Pashto | ps | ---
 | ps_AF | Afghanistan
Portuguese | pt | ---
 | pt_BR | Brazil
 | pt_PT | Portugal
Romanian | ro | ---
 | ro_MD | Moldova
 | ro_RO | Romania
Russian | ru | ---
 | ru_RU | Russia
 | ru_UA | Ukraine
Kinyarwanda | rw | ---
 | rw_RW | Rwanda
Sanskrit | sa | ---
 | sa_IN | India
Northern Sami | se | ---
 | se_FI | Finland
 | se_NO | Norway
Serbo-Croatian | sh | ---
 | sh_BA | Bosnia and Herzegovina
 | sh_CS | Serbia and Montenegro
 | sh_YU | Serbia
Sinhala | si | ---
 | si_LK | Sri Lanka
Sidamo | sid | ---
 | sid_ET | Ethiopia
Slovak | sk | ---
 | sk_SK | Slovakia
Slovenian | sl | ---
 | sl_SI | Slovenia
Somali | so | ---
 | so_DJ | Djibouti
 | so_ET | Ethiopia
 | so_KE | Kenya
 | so_SO | Somalia
Albanian | sq | ---
 | sq_AL | Albania
Serbian | sr | ---
 | sr_BA | Bosnia and Herzegovina
 | sr_CS | Serbia and Montenegro
 | sr_ME | Montenegro
 | sr_RS | Serbia
 | sr_YU | Serbia
Swati | ss | ---
 | ss_SZ | Swaziland
 | ss_ZA | South Africa
Southern Sotho | st | ---
 | st_LS | Lesotho
 | st_ZA | South Africa
Swedish | sv | ---
 | sv_FI | Finland
 | sv_SE | Sweden
Swahili | sw | ---
 | sw_KE | Kenya
 | sw_TZ | Tanzania
Syriac | syr | ---
 | syr_SY | Syria
Tamil | ta | ---
 | ta_IN | India
Telugu | te | ---
 | te_IN | India
Tajik | tg | ---
 | tg_TJ | Tajikistan
Thai | th | ---
 | th_TH | Thailand
Tigrinya | ti | ---
 | ti_ER | Eritrea
 | ti_ET | Ethiopia
Tigre | tig | ---
 | tig_ER | Eritrea
Tagalog | tl | ---
Tswana | tn | ---
 | tn_ZA | South Africa
Tonga | to | ---
 | to_TO | Tonga
Turkish | tr | ---
 | tr_TR | Turkey
Taroko | trv | ---
 | trv_TW | Taiwan
Tsonga | ts | ---
 | ts_ZA | South Africa
Tatar | tt | ---
 | tt_RU | Russia
Uighur | ug | ---
 | ug_CN | China
Ukrainian | uk | ---
 | uk_UA | Ukraine
Urdu | ur | ---
 | ur_IN | India
 | ur_PK | Pakistan
Uzbek | uz | ---
 | uz_AF | Afghanistan
 | uz_UZ | Uzbekistan
Venda | ve | ---
 | ve_ZA | South Africa
Vietnamese | vi | ---
 | vi_VN | Vietnam
Walamo | wal | ---
 | wal_ET | Ethiopia
Wolof | wo | ---
 | wo_SN | Senegal
Xhosa | xh | ---
 | xh_ZA | South Africa
Yoruba | yo | ---
 | yo_NG | Nigeria
Chinese | zh | ---
 | zh_CN | China
 | zh_HK | Hong Kong
 | zh_MO | Macau
 | zh_SG | Singapore
 | zh_TW | Taiwan
Zulu | zu | ---
 | zu_ZA | South Africa
Working with Dates and Times
Zend_Locale
Zend Framework手册 中文版
Zend_Log
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Locale
  • Introduction
  • Using Zend_Locale
  • Normalization and Localization
  • Working with Dates and Times
  • Supported locales


Zend_Log - Zend Framework Manual

Supported locales
Zend Framework Reference
Zend Framework手册 中文版
概述

Zend_Log

Table of Contents
  • 概述
  • Writers
  • Formatters
  • 过滤器
  • Using the Factory to Create a Log
Supported locales
Zend Framework Reference
Zend Framework手册 中文版
概述
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


概述 - Zend Framework Manual

Zend_Log
Zend_Log
Zend Framework手册 中文版
Writers

概述

Zend_Log 是一个通用日志组件. 它支持多个日志后端,格式化发送给日志的消息,过滤被纪录的消息.这些功能被划分为如下的对象:

  • 一个Log (Zend_Log的实例)是应用程序使用最多的对象.如果你想你可以有任意多的Log对象; 它们之间不会相互影响.一个Log对象必须至少包含一个Writer对象,可选的可以包含一个或多个Filter.

  • 一个 Writer (继承自Zend_Log_Writer_Abstract) 负责向存储中保存数据.

  • 一个 Filter (实现 Zend_Log_Filter_Interface接口)阻塞数据被保存.一个Filter可以应用到个别的Writer, 或则在所有Writer之前应用到一个Log.这样Filter是串联起来的.

  • 一个 Formatter (实现了 Zend_Log_Formatter_Interface接口) 在由Writer写入数据之前可以对日志数据进行格式化.每一个Writer只能有一个Formatter.

创建Log

如要启动日志纪录,实例化一个Writer并把它传递给Log实例:

$logger = new Zend_Log();
$writer = new Zend_Log_Writer_Stream('php://output');

$logger->addWriter($writer);
注意Log必须至少有一个Writer.你可以用addWriter方法添加任意数量的Writer.

你也可以直接把Writer传递给Log的构造函数:

$writer = new Zend_Log_Writer_Stream('php://output');
$logger = new Zend_Log($writer);
现在Log就可以使用了.

日志消息

要纪录消息,调用Log实例的log()方法,并向其传递消息和消息等级.

$logger->log('Informational message', Zend_Log::INFO);
log()方法的第一个参数是是一个字符串message,第二个参数是一个整数priority. priortiy必须是一个可以被Log实例识别的消息等级之一.这会在下一节解释.

有快捷的方法可以使用.而不是调用log()方法,你可以调用于消息等级同名的方法:

$logger->log('Informational message', Zend_Log::INFO);
$logger->info('Informational message');

$logger->log('Emergency message', Zend_Log::EMERG);
$logger->emerg('Emergency message');

销毁Log

如果Log对象不再需要,设置包含Log实例的变量为null即可销毁它. 这会在Log对象被销毁前自动地调用每个附加在Log上的Writer的shutdown()方法:

$logger = null;
在此方法中明确的销毁日志是可选的,并且在PHP关闭是自动执行.

使用内建的消息等级

Zend_Log 类定义了下面的消息等级:

EMERG   = 0;  // Emergency: 系统不可用
ALERT   = 1;  // Alert: 报警
CRIT    = 2;  // Critical: 紧要
ERR     = 3;  // Error: 错误
WARN    = 4;  // Warning: 警告
NOTICE  = 5;  // Notice: 通知
INFO    = 6;  // Informational: 一般信息
DEBUG   = 7;  // Debug: 小时消息
这些属性总是可用的.同样还可以使用其对应的快捷方法.

消息等级不是任意的,它们来自BSD的syslog协议,它们在 » RFC-3164 RFC文档中有阐述.名字和对应的消息等级号于其他PHP日志系统是兼容的, 例如» PEAR Log, 它也许能够和Zend_Log进行互操作.

消息等级号以重要性顺序排序.EMERG (0)是最重要的消息等级. DEBUG (7) 是内建属性中的次重要的消息等级.你可以定义重要性低于DEBUG的属性. 当在日志消息中选择消息等级时,要知道消息等级的层次并选择合适的消息等级.

添加用户定义的日志等级

用户定义的消息等级可以在运行时通过Log对象的addPriority()方法添加:

$logger->addPriority('FOO', 8);
上面的代码片断创建了一个新的日志消息等级, FOO,它的值为 8, 这个新的消息等级可以被用于日志:
$logger->log('Foo message', 8);
$logger->foo('Foo Message');
新的消息等级不能覆盖已有的.

理解日志事件

当你调用log()方法或它们的快捷方式时,日志事件即被创建.这是一个简单的关联数组, 它描述了传递给Writer的事件.下面的数组键总是在数组中创建:timestamp, message, priority, and priorityName.

event数组的创建是完全透明的.但是对于添加上面默认设置中不存在的项, 对event数组的了解是必须的.

给每个将来的事件添加新项,用给定的键值调用setEventItem()方法:

$logger->setEventItem('pid', getmypid());
上面的例子设置了一个名为pid的新项并设置它为当前进程的PID.一旦一个新的项被设置, 在日志纪录中,它自动对其他所有writer和所有事件数据可用.一个项可以在任何时候再次调用setEventItem() 方法被覆盖.

用setEventItem()设置一个新的事件项将导致新项发送给Logger的所有Writer.但是 这不能保证writer实际地纪录了该项.这是由于writer并不知道该怎么做,除非formatter通告了一个新项. 要了解更多,请查看Formatter.

Zend_Log
Zend_Log
Zend Framework手册 中文版
Writers
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Log
  • 概述
  • Writers
  • Formatters
  • 过滤器
  • Using the Factory to Create a Log


Writers - Zend Framework Manual

概述
Zend_Log
Zend Framework手册 中文版
Formatters

Writers

一个Writer是继承自Zend_Log_Writer_Abstract类的一个对象.Writer的职责是向存储后端纪录日志数据.

写入到流(Streams)

Zend_Log_Writer_Stream 写入日志数据到 » PHP 流中.

要把日志写入到输出缓冲区,使用URLphp:://output. 或则你可以直接发送日志数据到像STDERR 这样的流中(php://stderr).

$writer = new Zend_Log_Writer_Stream('php://output');
$logger = new Zend_Log($writer);

$logger->info('Informational message');

写入日志数据到一个文件,使用» Filesystem URLs之一:

$writer = new Zend_Log_Writer_Stream('/path/to/logfile');
$logger = new Zend_Log($writer);

$logger->info('Informational message');
默认情况流一个追加("a")的方式打开.要以不同的模式打开,Zend_Log_Writer_Stream 构造函数接受第二个参数作为可选的模式参数.

Zend_Log_Writer_Stream还接受一个现有的流资源:

$stream = @fopen('/path/to/logfile', 'a', false);
if (! $stream) {
    throw new Exception('Failed to open stream');
}

$writer = new Zend_Log_Writer_Stream($stream);
$logger = new Zend_Log($writer);

$logger->info('Informational message');
你不能给现有的流资源指定模式.这样作将导致抛出一个Zend_Log_Exception异常.

写入到数据库

Zend_Log_Writer_Db使用Zend_Db写入日志信息到数据库表中. Zend_Log_Writer_Db的构造函数接受一个Zend_Db_Adapter 实例,一个表名,和一个数据库字段到事件数据项的映射:

$params = array ('host'     => '127.0.0.1',
                 'username' => 'malory',
                 'password' => '******',
                 'dbname'   => 'camelot');
$db = Zend_Db::factory('PDO_MYSQL', $params);

$columnMapping = array('lvl' => 'priority', 'msg' => 'message');
$writer = new Zend_Log_Writer_Db($db, 'log_table_name', $columnMapping);

$logger = new Zend_Log($writer);

$logger->info('Informational message');
上面的例子写入单个行到名称为log_table_name的数据库表中.数据库字段lvs 接收优先级号,名为msg的字段接收日志消息.

踩熄Writer

Zend_Log_Writer_Null是一个不向任何地方写入任何数据的存根. 用于在测试期间关闭或踩熄日志.

$writer = new Zend_Log_Writer_Null;
$logger = new Zend_Log($writer);

// goes nowhere
$logger->info('Informational message');

测试 Mock

Zend_Log_Writer_Mock是一个非常简单的Writer,它纪录所接收到的原始的数据到到作为public属性的 数组中.

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

清空有mock记录的日志,设置$mock->events = array()即可.

组合Writers

没有复合Writer对象,但是一个Log实例可以有任意个Writer.使用addWriter方法 添加Writer:

$writer1 = new Zend_Log_Writer_Stream('/path/to/first/logfile');
$writer2 = new Zend_Log_Writer_Stream('/path/to/second/logfile');

$logger = new Zend_Log();
$logger->addWriter($writer1);
$logger->addWriter($writer2);

// goes to both writers
$logger->info('Informational message');

概述
Zend_Log
Zend Framework手册 中文版
Formatters
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Log
  • 概述
  • Writers
  • Formatters
  • 过滤器
  • Using the Factory to Create a Log


Formatters - Zend Framework Manual

Writers
Zend_Log
Zend Framework手册 中文版
过滤器

Formatters

Formatter是一个负责取得一个描述日志事件的event数组并输出一个格式化的日志行的对象.

有些Writer不是面向行的并且不能使用Formatter.一个例子是数据库Writer,它向数据库中直接插入一个事件项. 对于这样的Writer不支持Formatter,如果你对这样的Writer设置一个Formatter将抛出一个异常.

简单格式化

Zend_Log_Formatter_Simple 是默认的.当未指定任何formatter时使用. 默认的配置等同于下面的配置:

<?php
$format = '%timestamp% %priorityName% (%priority%): %message%' . PHP_EOL;
$formatter = new Zend_Log_Formatter_Simple($format);

使用Writer的steFormatter()方法在个别的Writer上设置Formatter:

<?php
$writer = new Zend_Log_Writer_Stream('php://output');
$formatter = new Zend_Log_Formatter_Simple('hello %message%' . PHP_EOL);
$writer->setFormatter($formatter);

$logger = new Zend_Log();
$logger->addWriter($writer);

$logger->info('there');

// outputs "hello there"

Zend_Log_Formatter_Simple的构造函数接受单个参数: 格式化字符串.该字符串包含有单个百分号包裹的键(例如,%message%). 格式化字符串可以包含来自于任何事件数据数组的键。在 Zend_Log_Formatter_Simple 里使用 DEFAULT_FORMAT 常量，可以获取缺省键。

格式化到XML

Zend_Log_Formatter_Xml格式化日志数据到XML字符串中. 默认,它自动地纪录在事件数据数组中的所有项.

<?php
$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');

上面的代码输出下面的XML(为清晰添加了空格):

<logEntry>
  <timestamp>2007-04-06T07:24:37-07:00</timestamp>
  <message>informational message</message>
  <priority>6</priority>
  <priorityName>INFO</priorityName>
</logEntry>

可以定制根元素并指定一个到事件数据数组的XML元素映射. Zend_Log_Formatter_Xml的构造函数接受一个根元素名字 的字符串作为第一个参数和一个元素映射的关联数组作为第二个参数:

<?php
$writer = new Zend_Log_Writer_Stream('php://output');
$formatter = new Zend_Log_Formatter_Xml('log', array('msg' => 'message', 'level' => 'priorityName'));
$writer->setFormatter($formatter);

$logger = new Zend_Log();
$logger->addWriter($writer);

$logger->info('informational message');
上面的代码改变默认的根元素logEntry为log. 还可以映射元素msg到事件数据项message,下面是输出结果:
<log>
  <msg>informational message</msg>
  <level>INFO</level>
</log>

Writers
Zend_Log
Zend Framework手册 中文版
过滤器
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Log
  • 概述
  • Writers
  • Formatters
  • 过滤器
  • Using the Factory to Create a Log


过滤器 - Zend Framework Manual

Formatters
Zend_Log
Zend Framework手册 中文版
Using the Factory to Create a Log

过滤器

一个Filter对象阻塞一个消息被写入到日志.

对所有Writer过滤

要在所有writer之前过滤消息,你可以使用addFilter()方法添加任意数量的Filter到Log对象:

$logger = new Zend_Log();

$writer = new Zend_Log_Writer_Stream('php://output');
$logger->addWriter($writer);

$filter = new Zend_Log_Filter_Priority(Zend_Log::CRIT);
$logger->addFilter($filter);

// blocked
$logger->info('Informational message');

// logged
$logger->emerg('Emergency message');
当你添加一个或多个Filter到Log对象后,消息在任何Writer接收之前必须通过所有的Filter.

过滤一个Writer实例

要在一个特定的Writer上进行消息过滤,使用该Writer对象的addFilter()方法:

$logger = new Zend_Log();

$writer1 = new Zend_Log_Writer_Stream('/path/to/first/logfile');
$logger->addWriter($writer1);

$writer2 = new Zend_Log_Writer_Stream('/path/to/second/logfile');
$logger->addWriter($writer2);

// add a filter only to writer2
$filter = new Zend_Log_Filter_Priority(Zend_Log::CRIT);
$writer2->addFilter($filter);

// logged to writer1, blocked from writer2
$logger->info('Informational message');

// logged by both writers
$logger->emerg('Emergency message');

Formatters
Zend_Log
Zend Framework手册 中文版
Using the Factory to Create a Log
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Log
  • 概述
  • Writers
  • Formatters
  • 过滤器
  • Using the Factory to Create a Log


Using the Factory to Create a Log - Zend Framework Manual

过滤器
Zend_Log
Zend Framework手册 中文版
Zend_Mail

Using the Factory to Create a Log

In addition to direct instantiation, you may also use the static factory() method to instantiate a Log instance, as well as to configure attached writers and their filters. Using the factory, you can attach zero or more writers. Configuration may be passed as either an array or a Zend_Config instance.

As an example:

  1. $logger = Zend_Log::factory(array(
  2.     array(
  3.         'writerName'   => 'Stream',
  4.         'writerParams' => array(
  5.             'stream'   => '/tmp/zend.log',
  6.         ),
  7.         'filterName'   => 'Priority',
  8.         'filterParams' => array(
  9.             'priority' => Zend_Log::WARN,
  10.         ),
  11.     ),
  12.     array(
  13.         'writerName'   => 'Firebug',
  14.         'filterName'   => 'Priority',
  15.         'filterParams' => array(
  16.             'priority' => Zend_Log::INFO,
  17.         ),
  18.     ),
  19. ));

The above will instantiate a logger with two writers, one for writing to a local file, another for sending data to Firebug. Each has an attached priority filter, with different maximum priorities.

Each writer can be defined with the following keys:

writerName (required)

The "short" name of a log writer; the name of the log writer minus the leading class prefix/namespace. See the "writerNamespace" entry below for more details. Examples: "Mock", "Stream", "Firebug".

writerParams (optional)

An associative array of parameters to use when instantiating the log writer. Each log writer's factory() method will map these to constructor arguments, as noted below.

writerNamespace (optional)

The class prefix/namespace to use when constructing the final log writer classname. By default, if this is not provided, "Zend_Log_Writer" is assumed; however, you can pass your own namespace if you are using a custom log writer.

filterName (optional)

The "short" name of a filter to use with the given log writer; the name of the filter minus the leading class prefix/namespace. See the "filterNamespace" entry below for more details. Examples: "Message", "Priority".

filterParams (optional)

An associative array of parameters to use when instantiating the log filter. Each log filter's factory() method will map these to constructor arguments, as noted below.

filterNamespace (optional)

The class prefix/namespace to use when constructing the final log filter classname. By default, if this is not provided, "Zend_Log_Filter" is assumed; however, you can pass your own namespace if you are using a custom log filter.

Each writer and each filter has specific options.

Writer Options

Zend_Log_Writer_Db Options

db

A Zend_Db_Adapter instance.

table

The name of the table in the RDBMS that will contain log entries.

columnMap

An associative array mapping database table column names to log event fields.

Zend_Log_Writer_Firebug Options

This log writer takes no options; any provided will be ignored.

Zend_Log_Writer_Mail Options

Zend_Log_Writer_Mail currently (as of 1.10) does not implement a factory, and will raise an exception if you attempt to instantiate it via Zend_Log::factory().

Zend_Log_Writer_Mock Options

This log writer takes no options; any provided will be ignored.

Zend_Log_Writer_Null Options

This log writer takes no options; any provided will be ignored.

Zend_Log_Writer_Stream Options

stream|url

A valid PHP stream identifier to which to log.

mode

The I/O mode with which to log; defaults to "a", for "append".

Zend_Log_Writer_Syslog Options

application

Application name used by the syslog writer.

facility

Facility used by the syslog writer.

Zend_Log_Writer_ZendMonitor Options

This log writer takes no options; any provided will be ignored.

Filter Options

Zend_Log_Filter_Message Options

regexp

Regular expression that must be matched in order to log a message.

Zend_Log_Filter_Priority Options

priority

The maximum priority level by which messages will be logged.

operator

The comparison operator by which to do priority comparisons; defaults to "<=".

Zend_Log_Writer_Suppress Options

This log filter takes no options; any provided will be ignored.

Creating Configurable Writers and Filters

If you find yourself needing to write your own log writers and/or filters, you can make them compatible with Zend_Log::factory() very easily.

At the minimum, you need to implement Zend_Log_FactoryInterface, which expects a static factory() method that accepts a single argument, $config, which may be either an array or Zend_Config object. If your log writer extends Zend_Log_Writer_Abstract, or your log filter extends Zend_Log_Filter_Abstract, you will pick this up for free.

Then, simply define mappings between the accepted configuration and any constructor arguments. As an example:

  1. class My_Log_Writer_Foo extends Zend_Log_Writer_Abstract
  2. {
  3.     public function __construct($bar, $baz)
  4.     {
  5.         // ...
  6.     }
  7.
  8.     public static function factory($config)
  9.     {
  10.         if ($config instanceof Zend_Config) {
  11.             $config = $config->toArray();
  12.         }
  13.         if (!is_array($config)) {
  14.             throw new Exception(
  15.                 'factory expects an array or Zend_Config instance'
  16.             );
  17.         }
  18.
  19.         $default = array(
  20.             'bar' => null,
  21.             'baz' => null,
  22.         );
  23.         $config = array_merge($default, $config);
  24.
  25.         return new self(
  26.             $config['bar'],
  27.             $config['baz']
  28.         );
  29.     }
  30. }

Alternately, you could call appropriate setters after instantiation, but prior to returning the instance:

  1. class My_Log_Writer_Foo extends Zend_Log_Writer_Abstract
  2. {
  3.     public function __construct($bar = null, $baz = null)
  4.     {
  5.         // ...
  6.     }
  7.
  8.     public function setBar($value)
  9.     {
  10.         // ...
  11.     }
  12.
  13.     public function setBaz($value)
  14.     {
  15.         // ...
  16.     }
  17.
  18.     public static function factory($config)
  19.     {
  20.         if ($config instanceof Zend_Config) {
  21.             $config = $config->toArray();
  22.         }
  23.         if (!is_array($config)) {
  24.             throw new Exception(
  25.                 'factory expects an array or Zend_Config instance'
  26.             );
  27.         }
  28.
  29.         $writer = new self();
  30.         if (isset($config['bar'])) {
  31.             $writer->setBar($config['bar']);
  32.         }
  33.         if (isset($config['baz'])) {
  34.             $writer->setBaz($config['baz']);
  35.         }
  36.         return $writer;
  37.     }
  38. }
过滤器
Zend_Log
Zend Framework手册 中文版
Zend_Mail
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Log
  • 概述
  • Writers
  • Formatters
  • 过滤器
  • Using the Factory to Create a Log


Zend_Mail - Zend Framework Manual

Using the Factory to Create a Log
Zend Framework Reference
Zend Framework手册 中文版
简介

Zend_Mail

Table of Contents
  • 简介
  • 通过SMTP发送邮件
  • 通过一个SMTP连接发送多个邮
  • 使用不同的Transport对象
  • HTML邮件
  • 附件
  • 增加收件人
  • 控制MIME分界线
  • 外加邮件头信息
  • 字符集
  • 编码
  • SMTP 身份验证
  • Securing SMTP Transport
  • Reading Mail Messages
Using the Factory to Create a Log
Zend Framework Reference
Zend Framework手册 中文版
简介
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


简介 - Zend Framework Manual

Zend_Mail
Zend_Mail
Zend Framework手册 中文版
通过SMTP发送邮件

简介

起步

Zend_Mail 提供了通用化的功能来撰写和发送文本以及兼容 MIME 标准的含有多个段的邮件消息。邮件在 Zend_Mail 里通过缺省的 Zend_Mail_Transport_Sendmail 传输或通过 Zend_Mail_Transport_Smtp 来发送。

Example #1 使用Zend_Mail发送简单邮件

一个简单邮件由一个或者几个收件人，一个主题，一个邮件主体和一个发件人组成。下面的步骤，使用 Zend_Mail_Transport_Sendmail 来发送邮件：

<?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();

Note: Minimum definitions
 使用Zend_Mail来发送邮件，你至少得指定一个收件人, 一个发件人(例如通过setFrom()方法)和一个邮件消息主体(文本 和/或者 HTML)。

通过“get”方法可以读取绝大多数储存在“mail”对象中的邮件属性，更进一步的细节请参阅API文档。getRecipients()是一个特例，它返回一个含有所有先前被加入的收件人地址的数组。

出于安全原因，Zend_Mail 过滤了邮件头中所有字段，以防止基于换行符(\n)邮件头注入(header injection)漏洞攻击。

你也可以使用大部分带有方便的 fluent interface 的 Zend_Mail 对象的方法。 Fluent interface 意思是每个方法返回一个引用到它被调用的对象，所以你可以立即调用其它方法。

<?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();

配置缺省的 sendmail 传送器（transport）

Zend_Mail 实例的缺省的传送器是 Zend_Mail_Transport_Sendmail，它是 PHP » mail() 函数的基本封装。如果你想传递另外的参数给 » mail() 函数，只需要创建一个新的传送器实例并传递参数给构造器。新的传送器实例可以当作缺省的 Zend_Mail 的传送器，或者它可以被传递给 Zend_Mail 的 send() 方法。

Example #2 传递另外的参数给 Zend_Mail_Transport_Sendmail 传送器

这个例子示范如何修改 » mail() 函数的返回路径。

<?php
require_once 'Zend/Mail.php';
require_once 'Zend/Mail/Transport/Sendmail.php';

$tr = new Zend_Mail_Transport_Sendmail('-freturn_to_me@example.com');
Zend_Mail::setDefaultTransport($tr);

$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();

Note: 安全模式限制
如果 PHP 运行在安全模式，另外的可选参数将导致 » mail() 函数失败。

Zend_Mail
Zend_Mail
Zend Framework手册 中文版
通过SMTP发送邮件
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Mail
  • 简介
  • 通过SMTP发送邮件
  • 通过一个SMTP连接发送多个邮
  • 使用不同的Transport对象
  • HTML邮件
  • 附件
  • 增加收件人
  • 控制MIME分界线
  • 外加邮件头信息
  • 字符集
  • 编码
  • SMTP 身份验证
  • Securing SMTP Transport
  • Reading Mail Messages


通过SMTP发送邮件 - Zend Framework Manual

简介
Zend_Mail
Zend Framework手册 中文版
通过一个SMTP连接发送多个邮

通过SMTP发送邮件

以SMTP方式发送邮件，Zend_Mail_Transport_Smtp对象需要在send()方法被调用之前创建并注册到Zend_Mail中去。当前脚本程序中所有使用Zend_Mail::send()发送的邮件，都将以SMTP方式传送：

Example #1 通过 SMTP 发送邮件

<?php
require_once 'Zend/Mail/Transport/Smtp.php';
$tr = new Zend_Mail_Transport_Smtp('mail.example.com');
Zend_Mail::setDefaultTransport($tr);

setDefaultTransport()方法的调用和Zend_Mail_Transport_Smtp对象的构造代价并不昂贵。这两行可以添加在脚本程序的配置文件(例如config.inc或者类似文件)中，从而为整个脚本程序配置Zend_Mail类的行为。如此可以把配置信息从应用程序逻辑分离出来邮件是通过SMTP还是» mail()发送，使用什么邮件服务器等等。

简介
Zend_Mail
Zend Framework手册 中文版
通过一个SMTP连接发送多个邮
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Mail
  • 简介
  • 通过SMTP发送邮件
  • 通过一个SMTP连接发送多个邮
  • 使用不同的Transport对象
  • HTML邮件
  • 附件
  • 增加收件人
  • 控制MIME分界线
  • 外加邮件头信息
  • 字符集
  • 编码
  • SMTP 身份验证
  • Securing SMTP Transport
  • Reading Mail Messages


通过一个SMTP连接发送多个邮 - Zend Framework Manual

通过SMTP发送邮件
Zend_Mail
Zend Framework手册 中文版
使用不同的Transport对象

通过一个SMTP连接发送多个邮

在缺省状态下，单个的 SMTP 传送器创建一个单个的连接并在整个脚本执行的生命周期重用，你可以这个 SMTP 连接发送多个邮件。每次投递之前发出一个 RSET 命令确保正确的 SMTP 握手被跟随。

Example #1 通过一个SMTP连接发送多个邮件

<?php
// Load classes
require_once 'Zend/Mail.php';

// Create transport
require_once 'Zend/Mail/Transport/Smtp.php';
$transport = new Zend_Mail_Transport_Smtp('localhost');

// Loop through messages
for ($i = 0; $i > 5; $i++) {
    $mail = new Zend_Mail();
    $mail->addTo('studio@peptolab.com', 'Test');
    $mail->setFrom('studio@peptolab.com', 'Test');
    $mail->setSubject('Demonstration - Sending Multiple Mails per SMTP Connection');
    $mail->setBodyText('...Your message here...');
    $mail->send($transport);
}

如果想给每个邮件投递配备一个单独的连接，你需要在 send()方法备调用的之前和之后创建和毁灭传送器；或者，在每个通过访问传送器协议对象投递之间处理连接。

Example #2 手工控制传送器连接

<?php

// Load classes
require_once 'Zend/Mail.php';

// Create transport
require_once 'Zend/Mail/Transport/Smtp.php';
$transport = new Zend_Mail_Transport_Smtp();

require_once 'Zend/Mail/Protocol/Smtp.php';
$protocol = new Zend_Mail_Protocol_Smtp('localhost');
$protocol->connect();
$protocol->helo('localhost');

$transport->setConnection($protocol);

// Loop through messages
for ($i = 0; $i > 5; $i++) {
    $mail = new Zend_Mail();
    $mail->addTo('studio@peptolab.com', 'Test');
    $mail->setFrom('studio@peptolab.com', 'Test');
    $mail->setSubject('Demonstration - Sending Multiple Mails per SMTP Connection');
    $mail->setBodyText('...Your message here...');

    // Manually control the connection
    $protocol->rset();
    $mail->send($transport);
}

$protocol->quit();
$protocol->disconnect();
通过SMTP发送邮件
Zend_Mail
Zend Framework手册 中文版
使用不同的Transport对象
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Mail
  • 简介
  • 通过SMTP发送邮件
  • 通过一个SMTP连接发送多个邮
  • 使用不同的Transport对象
  • HTML邮件
  • 附件
  • 增加收件人
  • 控制MIME分界线
  • 外加邮件头信息
  • 字符集
  • 编码
  • SMTP 身份验证
  • Securing SMTP Transport
  • Reading Mail Messages


使用不同的Transport对象 - Zend Framework Manual

通过一个SMTP连接发送多个邮
Zend_Mail
Zend Framework手册 中文版
HTML邮件

使用不同的Transport对象

有时你想想使用不同的连接来发送不同的邮件，你也可以不预先调用setDefaultTransport()方法，而直接将Transport对象传递给send()。被传递的transport对象会在实际的send()调用中替代缺省的transport：

Example #1 使用不同的Transport对象

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

Note: 外加的transports
 外加transport，需要实现Zend_Mail_Transport_Interface接口。

通过一个SMTP连接发送多个邮
Zend_Mail
Zend Framework手册 中文版
HTML邮件
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Mail
  • 简介
  • 通过SMTP发送邮件
  • 通过一个SMTP连接发送多个邮
  • 使用不同的Transport对象
  • HTML邮件
  • 附件
  • 增加收件人
  • 控制MIME分界线
  • 外加邮件头信息
  • 字符集
  • 编码
  • SMTP 身份验证
  • Securing SMTP Transport
  • Reading Mail Messages


HTML邮件 - Zend Framework Manual

使用不同的Transport对象
Zend_Mail
Zend Framework手册 中文版
附件

HTML邮件

发送HTML格式的邮件，使用setBodyHTML()方法来设置邮件正文而不是setBodyText()方法，MIME类型会被自动设置为text/html。如果你既使用HTML又使用纯文本, 那么multipart/alternative MIME类型的邮件消息将会自动产生：

Example #1 发送HTML邮件

<?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();
使用不同的Transport对象
Zend_Mail
Zend Framework手册 中文版
附件
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Mail
  • 简介
  • 通过SMTP发送邮件
  • 通过一个SMTP连接发送多个邮
  • 使用不同的Transport对象
  • HTML邮件
  • 附件
  • 增加收件人
  • 控制MIME分界线
  • 外加邮件头信息
  • 字符集
  • 编码
  • SMTP 身份验证
  • Securing SMTP Transport
  • Reading Mail Messages


附件 - Zend Framework Manual

HTML邮件
Zend_Mail
Zend Framework手册 中文版
增加收件人

附件

使用createAttachment()方法可以将文件附加到邮件中。Zend_Mail会缺省地认为该文件是二进制对象(application/octet-stream)，以 base64编码传输, 并且作为邮件的附件处理。通过传递额外的参数给createAttachment()方法可以覆盖上述缺省设定：

Example #1 带附件的邮件

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

如果你想得到对此附件MIME段产生的更多控制，你可以使用createAttachment()方法的返回值来修改它的属性。方法createAttachment()返回了一个Zend_Mime_Part对象：

<?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();

创建 Zend_Mime_Part 实例和用 addAttachment() 添加它的替代方案：

<?php
require_once 'Zend/Mail.php';
$mail = new Zend_Mail();

$at = new Zend_Mime_Part($myImage);
$at->type        = 'image/gif';
$at->disposition = Zend_Mime::DISPOSITION_INLINE;
$at->encoding    = Zend_Mime::ENCODING_8BIT;
$at->filename    = 'test.gif';

$mail->addAttachment($at);

$mail->send();
HTML邮件
Zend_Mail
Zend Framework手册 中文版
增加收件人
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Mail
  • 简介
  • 通过SMTP发送邮件
  • 通过一个SMTP连接发送多个邮
  • 使用不同的Transport对象
  • HTML邮件
  • 附件
  • 增加收件人
  • 控制MIME分界线
  • 外加邮件头信息
  • 字符集
  • 编码
  • SMTP 身份验证
  • Securing SMTP Transport
  • Reading Mail Messages


增加收件人 - Zend Framework Manual

附件
Zend_Mail
Zend Framework手册 中文版
控制MIME分界线

增加收件人

有三种方法可以增加收件人：

  • addTo()：增加一个收件人到邮件头“To”（收件人）

  • addCc()：增加一个收件人到邮件头“Cc”（抄送）

  • addBcc()：增加一个收件人到邮件头“Bcc”（暗送）

Note: 附加的参数
 addTo()和addCc()接受可选的第二个参数用于为邮件头的收件人指定具有可读性的名字。

附件
Zend_Mail
Zend Framework手册 中文版
控制MIME分界线
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Mail
  • 简介
  • 通过SMTP发送邮件
  • 通过一个SMTP连接发送多个邮
  • 使用不同的Transport对象
  • HTML邮件
  • 附件
  • 增加收件人
  • 控制MIME分界线
  • 外加邮件头信息
  • 字符集
  • 编码
  • SMTP 身份验证
  • Securing SMTP Transport
  • Reading Mail Messages


控制MIME分界线 - Zend Framework Manual

增加收件人
Zend_Mail
Zend Framework手册 中文版
外加邮件头信息

控制MIME分界线

在一个包含多个段的邮件里，用于分隔邮件不同段的MIME分界线(MIME boundary)通常是随机生成的。但是在某些情况下，你也许会希望使用特定的MIME分界线。如下面的例子所示，你可以使用setMimeBoundary()方法来做到这一点：

Example #1 更改MIME分界线

$mail = new Zend_Mail();
$mail->setMimeBoundary('=_' . md5(microtime(1) . $someId++));
// build message...
增加收件人
Zend_Mail
Zend Framework手册 中文版
外加邮件头信息
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Mail
  • 简介
  • 通过SMTP发送邮件
  • 通过一个SMTP连接发送多个邮
  • 使用不同的Transport对象
  • HTML邮件
  • 附件
  • 增加收件人
  • 控制MIME分界线
  • 外加邮件头信息
  • 字符集
  • 编码
  • SMTP 身份验证
  • Securing SMTP Transport
  • Reading Mail Messages


外加邮件头信息 - Zend Framework Manual

控制MIME分界线
Zend_Mail
Zend Framework手册 中文版
字符集

外加邮件头信息

使用addHeader()方法可以外加任意的邮件头信息。它需要两个参数，头信息的名称和值，第三个可选的参数，它决定了该邮件头信息是否可以有多个值：

Example #1 外加邮件头信息

<?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);
控制MIME分界线
Zend_Mail
Zend Framework手册 中文版
字符集
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Mail
  • 简介
  • 通过SMTP发送邮件
  • 通过一个SMTP连接发送多个邮
  • 使用不同的Transport对象
  • HTML邮件
  • 附件
  • 增加收件人
  • 控制MIME分界线
  • 外加邮件头信息
  • 字符集
  • 编码
  • SMTP 身份验证
  • Securing SMTP Transport
  • Reading Mail Messages


字符集 - Zend Framework Manual

外加邮件头信息
Zend_Mail
Zend Framework手册 中文版
编码

字符集

Zend_Mail不会对邮件段字符集的正确性进行检查。当Zend_Mail初始化的时候，缺省地为邮件设置了iso8859-1字符集。程序必须确保添加至邮件对象的所有段都以正确的字符集编码。在添加一个新的邮件段时，可以为每个段指定不同的字符集。

Note: 只限于文本(Text)格式
 字符集只适用于文本格式中的段。

外加邮件头信息
Zend_Mail
Zend Framework手册 中文版
编码
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Mail
  • 简介
  • 通过SMTP发送邮件
  • 通过一个SMTP连接发送多个邮
  • 使用不同的Transport对象
  • HTML邮件
  • 附件
  • 增加收件人
  • 控制MIME分界线
  • 外加邮件头信息
  • 字符集
  • 编码
  • SMTP 身份验证
  • Securing SMTP Transport
  • Reading Mail Messages


编码 - Zend Framework Manual

字符集
Zend_Mail
Zend Framework手册 中文版
SMTP 身份验证

编码

文本和HTML信息在缺省下以Quoted-printable机制编码。在调用addAttachment()方法添加附件的时候， 如果没有指定编码方式，都将以base64方式编码，或稍后通过给MIME段对象(Zend_Mime_Part)相应属性赋值来指定编码方式。 7Bit和8Bit编码目前仅仅在二进制数据上可行。

Zend_Mail_Transport_Smtp编码行以一个点(.)或者两个点(..)起始，以确保邮件不违反SMTP协议。

字符集
Zend_Mail
Zend Framework手册 中文版
SMTP 身份验证
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Mail
  • 简介
  • 通过SMTP发送邮件
  • 通过一个SMTP连接发送多个邮
  • 使用不同的Transport对象
  • HTML邮件
  • 附件
  • 增加收件人
  • 控制MIME分界线
  • 外加邮件头信息
  • 字符集
  • 编码
  • SMTP 身份验证
  • Securing SMTP Transport
  • Reading Mail Messages


SMTP 身份验证 - Zend Framework Manual

编码
Zend_Mail
Zend Framework手册 中文版
Securing SMTP Transport

SMTP 身份验证

Zend_Mail 支持使用 SMTP 身份验证，通过配置数组传递“auth”参数到 Zend_Mail_Transport_Smtp 的构造函数中。可用的内建身份验证方法为 PLAIN，LOGIN 和 CRAM-MD5，这些都需要在配置数组中设置“username”和“password”。

Example #1 在 Zend_Mail_Transport_Smtp 中使用身份验证

<?php

            require_once 'Zend/Mail.php';
            require_once 'Zend/Mail/Transport/Smtp.php';

            $config = array('auth' => 'login',
            'username' => 'myusername',
            'password' => 'password');

            $transport = new Zend_Mail_Transport_Smtp('mail.server.com', $config);

            $mail = new Zend_Mail();
            $mail->setBodyText('This is the text of the mail.');
            $mail->setFrom('sender@test.com', 'Some Sender');
            $mail->addTo('recipient@test.com', 'Some Recipient');
            $mail->setSubject('TestSubject');
            $mail->send($transport);

Note: 身份验证类型
 身份验证的类型是大小写不敏感的，但是不能有标点符号。例如，使用 CRAM-MD5 类型，则应当传递 'auth' => 'crammd5' 到 Zend_Mail_Transport_Smtp 的构造函数中。

编码
Zend_Mail
Zend Framework手册 中文版
Securing SMTP Transport
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Mail
  • 简介
  • 通过SMTP发送邮件
  • 通过一个SMTP连接发送多个邮
  • 使用不同的Transport对象
  • HTML邮件
  • 附件
  • 增加收件人
  • 控制MIME分界线
  • 外加邮件头信息
  • 字符集
  • 编码
  • SMTP 身份验证
  • Securing SMTP Transport
  • Reading Mail Messages


Securing SMTP Transport - Zend Framework Manual

SMTP 身份验证
Zend_Mail
Zend Framework手册 中文版
Reading Mail Messages

Securing SMTP Transport

Zend_Mail also supports the use of either TLS or SSL to secure a SMTP connection. This can be enabled be passing the 'ssl' parameter to the configuration array in the Zend_Mail_Transport_Smtp constructor with a value of either 'ssl' or 'tls'. A port can optionally be supplied, otherwise it defaults to 25 for TLS or 465 for SSL.

Example #1 Enabling a secure connection within Zend_Mail_Transport_Smtp

  1. $config = array('ssl' => 'tls',
  2.                 'port' => 25); // Optional port number supplied
  3.
  4. $transport = new Zend_Mail_Transport_Smtp('mail.server.com', $config);
  5.
  6. $mail = new Zend_Mail();
  7. $mail->setBodyText('This is the text of the mail.');
  8. $mail->setFrom('sender@test.com', 'Some Sender');
  9. $mail->addTo('recipient@test.com', 'Some Recipient');
  10. $mail->setSubject('TestSubject');
  11. $mail->send($transport);
SMTP 身份验证
Zend_Mail
Zend Framework手册 中文版
Reading Mail Messages
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Mail
  • 简介
  • 通过SMTP发送邮件
  • 通过一个SMTP连接发送多个邮
  • 使用不同的Transport对象
  • HTML邮件
  • 附件
  • 增加收件人
  • 控制MIME分界线
  • 外加邮件头信息
  • 字符集
  • 编码
  • SMTP 身份验证
  • Securing SMTP Transport
  • Reading Mail Messages


Reading Mail Messages - Zend Framework Manual

Securing SMTP Transport
Zend_Mail
Zend Framework手册 中文版
Zend_Markup

Reading Mail Messages

Zend_Mail can read mail messages from several local or remote mail storages. All of them have the same basic API to count and fetch messages and some of them implement additional interfaces for not so common features. For a feature overview of the implemented storages see the following table.

Mail Read Feature Overview
Feature | Mbox | Maildir | Pop3 | IMAP
Storage type | local | local | remote | remote
Fetch message | Yes | Yes | Yes | Yes
Fetch MIME-part | emulated | emulated | emulated | emulated
Folders | Yes | Yes | No | Yes
Create message/folder | No | todo | No | todo
Flags | No | Yes | No | Yes
Quota | No | Yes | No | No

Simple example using Pop3

  1. $mail = new Zend_Mail_Storage_Pop3(array('host'     => 'localhost',
  2.                                          'user'     => 'test',
  3.                                          'password' => 'test'));
  4.
  5. echo $mail->countMessages() . " messages found\n";
  6. foreach ($mail as $message) {
  7.     echo "Mail from '{$message->from}': {$message->subject}\n";
  8. }

Opening a local storage

Mbox and Maildir are the two supported formats for local mail storages, both in their most simple formats.

If you want to read from a Mbox file you only need to give the filename to the constructor of Zend_Mail_Storage_Mbox:

  1. $mail = new Zend_Mail_Storage_Mbox(array('filename' =>
  2.                                              '/home/test/mail/inbox'));

Maildir is very similar but needs a dirname:

  1. $mail = new Zend_Mail_Storage_Maildir(array('dirname' =>
  2.                                                 '/home/test/mail/'));

Both constructors throw a Zend_Mail_Exception if the storage can't be read.

Opening a remote storage

For remote storages the two most popular protocols are supported: Pop3 and Imap. Both need at least a host and a user to connect and login. The default password is an empty string, the default port as given in the protocol RFC.

  1. // connecting with Pop3
  2. $mail = new Zend_Mail_Storage_Pop3(array('host'     => 'example.com',
  3.                                          'user'     => 'test',
  4.                                          'password' => 'test'));
  5.
  6. // connecting with Imap
  7. $mail = new Zend_Mail_Storage_Imap(array('host'     => 'example.com',
  8.                                          'user'     => 'test',
  9.                                          'password' => 'test'));
  10.
  11. // example for a none standard port
  12. $mail = new Zend_Mail_Storage_Pop3(array('host'     => 'example.com',
  13.                                          'port'     => 1120
  14.                                          'user'     => 'test',
  15.                                          'password' => 'test'));

For both storages SSL and TLS are supported. If you use SSL the default port changes as given in the RFC.

  1. // examples for Zend_Mail_Storage_Pop3, same works for Zend_Mail_Storage_Imap
  2.
  3. // use SSL on different port (default is 995 for Pop3 and 993 for Imap)
  4. $mail = new Zend_Mail_Storage_Pop3(array('host'     => 'example.com',
  5.                                          'user'     => 'test',
  6.                                          'password' => 'test',
  7.                                          'ssl'      => 'SSL'));
  8.
  9. // use TLS
  10. $mail = new Zend_Mail_Storage_Pop3(array('host'     => 'example.com',
  11.                                          'user'     => 'test',
  12.                                          'password' => 'test',
  13.                                          'ssl'      => 'TLS'));

Both constructors can throw Zend_Mail_Exception or Zend_Mail_Protocol_Exception (extends Zend_Mail_Exception), depending on the type of error.

Fetching messages and simple methods

Messages can be fetched after you've opened the storage . You need the message number, which is a counter starting with 1 for the first message. To fetch the message, you use the method getMessage():

  1. $message = $mail->getMessage($messageNum);

Array access is also supported, but this access method won't supported any additional parameters that could be added to getMessage(). As long as you don't mind, and can live with the default values, you may use:

  1. $message = $mail[$messageNum];

For iterating over all messages the Iterator interface is implemented:

  1. foreach ($mail as $messageNum => $message) {
  2.     // do stuff ...
  3. }

To count the messages in the storage, you can either use the method countMessages() or use array access:

  1. // method
  2. $maxMessage = $mail->countMessages();
  3.
  4. // array access
  5. $maxMessage = count($mail);

To remove a mail, you use the method removeMessage() or again array access:

  1. // method
  2. $mail->removeMessage($messageNum);
  3.
  4. // array access
  5. unset($mail[$messageNum]);

Working with messages

After you fetch the messages with getMessage() you want to fetch headers, the content or single parts of a multipart message. All headers can be accessed via properties or the method getHeader() if you want more control or have unusual header names. The header names are lower-cased internally, thus the case of the header name in the mail message doesn't matter. Also headers with a dash can be written in camel-case. If no header is found for both notations an exception is thrown. To encounter this the method headerExists() can be used to check the existance of a header.

  1. // get the message object
  2. $message = $mail->getMessage(1);
  3.
  4. // output subject of message
  5. echo $message->subject . "\n";
  6.
  7. // get content-type header
  8. $type = $message->contentType;
  9.
  10. // check if CC isset:
  11. if( isset($message->cc) ) { // or $message->headerExists('cc');
  12.     $cc = $message->cc;
  13. }

If you have multiple headers with the same name- i.e. the Received headers- you might want an array instead of a string. In this case, use the getHeader() method.

  1. // get header as property - the result is always a string,
  2. // with new lines between the single occurrences in the message
  3. $received = $message->received;
  4.
  5. // the same via getHeader() method
  6. $received = $message->getHeader('received', 'string');
  7.
  8. // better an array with a single entry for every occurrences
  9. $received = $message->getHeader('received', 'array');
  10. foreach ($received as $line) {
  11.     // do stuff
  12. }
  13.
  14. // if you don't define a format you'll get the internal representation
  15. // (string for single headers, array for multiple)
  16. $received = $message->getHeader('received');
  17. if (is_string($received)) {
  18.     // only one received header found in message
  19. }

The method getHeaders() returns all headers as array with the lower-cased name as key and the value as and array for multiple headers or as string for single headers.

  1. // dump all headers
  2. foreach ($message->getHeaders() as $name => $value) {
  3.     if (is_string($value)) {
  4.         echo "$name: $value\n";
  5.         continue;
  6.     }
  7.     foreach ($value as $entry) {
  8.         echo "$name: $entry\n";
  9.     }
  10. }

If you don't have a multipart message, fetching the content is easily done via getContent(). Unlike the headers, the content is only fetched when needed (aka late-fetch).

  1. // output message content for HTML
  2. echo '<pre>';
  3. echo $message->getContent();
  4. echo '</pre>';

Checking for multipart messages is done with the method isMultipart(). If you have multipart message you can get an instance of Zend_Mail_Part with the method getPart(). Zend_Mail_Part is the base class of Zend_Mail_Message, so you have the same methods: getHeader(), getHeaders(), getContent(), getPart(), isMultipart and the properties for headers.

  1. // get the first none multipart part
  2. $part = $message;
  3. while ($part->isMultipart()) {
  4.     $part = $message->getPart(1);
  5. }
  6. echo 'Type of this part is ' . strtok($part->contentType, ';') . "\n";
  7. echo "Content:\n";
  8. echo $part->getContent();

Zend_Mail_Part also implements RecursiveIterator, which makes it easy to scan through all parts. And for easy output, it also implements the magic method __toString(), which returns the content.

  1. // output first text/plain part
  2. $foundPart = null;
  3. foreach (new RecursiveIteratorIterator($mail->getMessage(1)) as $part) {
  4.     try {
  5.         if (strtok($part->contentType, ';') == 'text/plain') {
  6.             $foundPart = $part;
  7.             break;
  8.         }
  9.     } catch (Zend_Mail_Exception $e) {
  10.         // ignore
  11.     }
  12. }
  13. if (!$foundPart) {
  14.     echo 'no plain text part found';
  15. } else {
  16.     echo "plain text part: \n" . $foundPart;
  17. }

Checking for flags

Maildir and IMAP support storing flags. The class Zend_Mail_Storage has constants for all known maildir and IMAP system flags, named Zend_Mail_Storage::FLAG_<flagname>. To check for flags Zend_Mail_Message has a method called hasFlag(). With getFlags() you'll get all set flags.

  1. // find unread messages
  2. echo "Unread mails:\n";
  3. foreach ($mail as $message) {
  4.     if ($message->hasFlag(Zend_Mail_Storage::FLAG_SEEN)) {
  5.         continue;
  6.     }
  7.     // mark recent/new mails
  8.     if ($message->hasFlag(Zend_Mail_Storage::FLAG_RECENT)) {
  9.         echo '! ';
  10.     } else {
  11.         echo '  ';
  12.     }
  13.     echo $message->subject . "\n";
  14. }
  15.
  16. // check for known flags
  17. $flags = $message->getFlags();
  18. echo "Message is flagged as: ";
  19. foreach ($flags as $flag) {
  20.     switch ($flag) {
  21.         case Zend_Mail_Storage::FLAG_ANSWERED:
  22.             echo 'Answered ';
  23.             break;
  24.         case Zend_Mail_Storage::FLAG_FLAGGED:
  25.             echo 'Flagged ';
  26.             break;
  27.
  28.         // ...
  29.         // check for other flags
  30.         // ...
  31.
  32.         default:
  33.             echo $flag . '(unknown flag) ';
  34.     }
  35. }

As IMAP allows user or client defined flags, you could get flags that don't have a constant in Zend_Mail_Storage. Instead, they are returned as strings and can be checked the same way with hasFlag().

  1. // check message for client defined flags $IsSpam, $SpamTested
  2. if (!$message->hasFlag('$SpamTested')) {
  3.     echo 'message has not been tested for spam';
  4. } else if ($message->hasFlag('$IsSpam')) {
  5.     echo 'this message is spam';
  6. } else {
  7.     echo 'this message is ham';
  8. }

Using folders

All storages, except Pop3, support folders, also called mailboxes. The interface implemented by all storages supporting folders is called Zend_Mail_Storage_Folder_Interface. Also all of these classes have an additional optional parameter called folder, which is the folder selected after login, in the constructor.

For the local storages you need to use separate classes called Zend_Mail_Storage_Folder_Mbox or Zend_Mail_Storage_Folder_Maildir. Both need one parameter called dirname with the name of the base dir. The format for maildir is as defined in maildir++ (with a dot as default delimiter), Mbox is a directory hierarchy with Mbox files. If you don't have a Mbox file called INBOX in your Mbox base dir you need to set another folder in the constructor.

Zend_Mail_Storage_Imap already supports folders by default. Examples for opening these storages:

  1. // mbox with folders
  2. $mail = new Zend_Mail_Storage_Folder_Mbox(array('dirname' =>
  3.                                                     '/home/test/mail/'));
  4.
  5. // mbox with a default folder not called INBOX, also works
  6. // with Zend_Mail_Storage_Folder_Maildir and Zend_Mail_Storage_Imap
  7. $mail = new Zend_Mail_Storage_Folder_Mbox(array('dirname' =>
  8.                                                     '/home/test/mail/',
  9.                                                 'folder'  =>
  10.                                                     'Archive'));
  11.
  12. // maildir with folders
  13. $mail = new Zend_Mail_Storage_Folder_Maildir(array('dirname' =>
  14.                                                        '/home/test/mail/'));
  15.
  16. // maildir with colon as delimiter, as suggested in Maildir++
  17. $mail = new Zend_Mail_Storage_Folder_Maildir(array('dirname' =>
  18.                                                        '/home/test/mail/',
  19.                                                    'delim'   => ':'));
  20.
  21. // imap is the same with and without folders
  22. $mail = new Zend_Mail_Storage_Imap(array('host'     => 'example.com',
  23.                                          'user'     => 'test',
  24.                                          'password' => 'test'));

With the method getFolders($root = null) you can get the folder hierarchy starting with the root folder or the given folder. It's returned as an instance of Zend_Mail_Storage_Folder, which implements RecursiveIterator and all children are also instances of Zend_Mail_Storage_Folder. Each of these instances has a local and a global name returned by the methods getLocalName() and getGlobalName(). The global name is the absolute name from the root folder (including delimiters), the local name is the name in the parent folder.

Mail Folder Names
Global Name | Local Name
/INBOX | INBOX
/Archive/2005 | 2005
List.ZF.General | General

If you use the iterator, the key of the current element is the local name. The global name is also returned by the magic method __toString(). Some folders may not be selectable, which means they can't store messages and selecting them results in an error. This can be checked with the method isSelectable(). So it's very easy to output the whole tree in a view:

  1. $folders = new RecursiveIteratorIterator($this->mail->getFolders(),
  2.                                          RecursiveIteratorIterator::SELF_FIRST);
  3. echo '<select name="folder">';
  4. foreach ($folders as $localName => $folder) {
  5.     $localName = str_pad('', $folders->getDepth(), '-', STR_PAD_LEFT) .
  6.                  $localName;
  7.     echo '<option';
  8.     if (!$folder->isSelectable()) {
  9.         echo ' disabled="disabled"';
  10.     }
  11.     echo ' value="' . htmlspecialchars($folder) . '">'
  12.         . htmlspecialchars($localName) . '</option>';
  13. }
  14. echo '</select>';

The current selected folder is returned by the method getSelectedFolder(). Changing the folder is done with the method selectFolder(), which needs the global name as parameter. If you want to avoid to write delimiters you can also use the properties of a Zend_Mail_Storage_Folder instance:

  1. // depending on your mail storage and its settings $rootFolder->Archive->2005
  2. // is the same as:
  3. //   /Archive/2005
  4. //  Archive:2005
  5. //  INBOX.Archive.2005
  6. //  ...
  7. $folder = $mail->getFolders()->Archive->2005;
  8. echo 'Last folder was '
  9.    . $mail->getSelectedFolder()
  10.    . "new folder is $folder\n";
  11. $mail->selectFolder($folder);

Advanced Use

Using NOOP

If you're using a remote storage and have some long tasks you might need to keep the connection alive via noop:

  1. foreach ($mail as $message) {
  2.
  3.     // do some calculations ...
  4.
  5.     $mail->noop(); // keep alive
  6.
  7.     // do something else ...
  8.
  9.     $mail->noop(); // keep alive
  10. }

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 your Mbox or Maildir storage should not change. Some easy checks may be done, like reparsing the current Mbox file if the modification time changes, or reparsing the folder structure if a folder has vanished (which still results in an error, but you can search for another folder afterwards). It's better if you have something like a signal file for changes and check it before using the cached instance.

  1. // there's no specific cache handler/class used here,
  2. // change the code to match your cache handler
  3. $signal_file = '/home/test/.mail.last_change';
  4. $mbox_basedir = '/home/test/mail/';
  5. $cache_id = 'example mail cache ' . $mbox_basedir . $signal_file;
  6.
  7. $cache = new Your_Cache_Class();
  8. if (!$cache->isCached($cache_id) ||
  9.     filemtime($signal_file) > $cache->getMTime($cache_id)) {
  10.     $mail = new Zend_Mail_Storage_Folder_Pop3(array('dirname' =>
  11.                                                         $mbox_basedir));
  12. } else {
  13.     $mail = $cache->get($cache_id);
  14. }
  15.
  16. // do stuff ...
  17.
  18. $cache->set($cache_id, $mail);

Extending Protocol Classes

Remote storages use two classes: Zend_Mail_Storage_<Name> and Zend_Mail_Protocol_<Name>. The protocol class translates the protocol commands and responses from and to PHP, like methods for the commands or variables with different structures for data. The other/main class implements the common interface.

If you need additional protocol features, you can extend the protocol class and use it in the constructor of the main class. As an example, assume we need to knock different ports before we can connect to POP3.

  1. class Example_Mail_Exception extends Zend_Mail_Exception
  2. {
  3. }
  4.
  5. class Example_Mail_Protocol_Exception extends Zend_Mail_Protocol_Exception
  6. {
  7. }
  8.
  9. class Example_Mail_Protocol_Pop3_Knock extends Zend_Mail_Protocol_Pop3
  10. {
  11.     private $host, $port;
  12.
  13.     public function __construct($host, $port = null)
  14.     {
  15.         // no auto connect in this class
  16.         $this->host = $host;
  17.         $this->port = $port;
  18.     }
  19.
  20.     public function knock($port)
  21.     {
  22.         $sock = @fsockopen($this->host, $port);
  23.         if ($sock) {
  24.             fclose($sock);
  25.         }
  26.     }
  27.
  28.     public function connect($host = null, $port = null, $ssl = false)
  29.     {
  30.         if ($host === null) {
  31.             $host = $this->host;
  32.         }
  33.         if ($port === null) {
  34.             $port = $this->port;
  35.         }
  36.         parent::connect($host, $port);
  37.     }
  38. }
  39.
  40. class Example_Mail_Pop3_Knock extends Zend_Mail_Storage_Pop3
  41. {
  42.     public function __construct(array $params)
  43.     {
  44.         // ... check $params here! ...
  45.         $protocol = new Example_Mail_Protocol_Pop3_Knock($params['host']);
  46.
  47.         // do our "special" thing
  48.         foreach ((array)$params['knock_ports'] as $port) {
  49.             $protocol->knock($port);
  50.         }
  51.
  52.         // get to correct state
  53.         $protocol->connect($params['host'], $params['port']);
  54.         $protocol->login($params['user'], $params['password']);
  55.
  56.         // initialize parent
  57.         parent::__construct($protocol);
  58.     }
  59. }
  60.
  61. $mail = new Example_Mail_Pop3_Knock(array('host'        => 'localhost',
  62.                                           'user'        => 'test',
  63.                                           'password'    => 'test',
  64.                                           'knock_ports' =>
  65.                                               array(1101, 1105, 1111)));

As you see, we always assume we're connected, logged in and, if supported, a folder is selected in the constructor of the main class. Thus if you assign your own protocol class, you always need to make sure that's done or the next method will fail if the server doesn't allow it in the current state.

Using Quota (since 1.5)

Zend_Mail_Storage_Writable_Maildir has support for Maildir++ quotas. It's disabled by default, but it's possible to use it manually, if the automatic checks are not desired (this means appendMessage(), removeMessage() and copyMessage() do no checks and do not add entries to the maildirsize file). If enabled, an exception is thrown if you try to write to the maildir and it's already over quota.

There are three methods used for quotas: getQuota(), setQuota() and checkQuota():

  1. $mail = new Zend_Mail_Storage_Writable_Maildir(array('dirname' =>
  2.                                                    '/home/test/mail/'));
  3. $mail->setQuota(true); // true to enable, false to disable
  4. echo 'Quota check is now ', $mail->getQuota() ? 'enabled' : 'disabled', "\n";
  5. // check quota can be used even if quota checks are disabled
  6. echo 'You are ', $mail->checkQuota() ? 'over quota' : 'not over quota', "\n";

checkQuota() can also return a more detailed response:

  1. $quota = $mail->checkQuota(true);
  2. echo 'You are ', $quota['over_quota'] ? 'over quota' : 'not over quota', "\n";
  3. echo 'You have ',
  4.      $quota['count'],
  5.      ' of ',
  6.      $quota['quota']['count'],
  7.      ' messages and use ';
  8. echo $quota['size'], ' of ', $quota['quota']['size'], ' octets';

If you want to specify your own quota instead of using the one specified in the maildirsize file you can do with setQuota():

  1. // message count and octet size supported, order does matter
  2. $quota = $mail->setQuota(array('size' => 10000, 'count' => 100));

To add your own quota checks use single letters as keys, and they will be preserved (but obviously not checked). It's also possible to extend Zend_Mail_Storage_Writable_Maildir to define your own quota only if the maildirsize file is missing (which can happen in Maildir++):

  1. class Example_Mail_Storage_Maildir extends Zend_Mail_Storage_Writable_Maildir {
  2.     // getQuota is called with $fromStorage = true by quota checks
  3.     public function getQuota($fromStorage = false) {
  4.         try {
  5.             return parent::getQuota($fromStorage);
  6.         } catch (Zend_Mail_Storage_Exception $e) {
  7.             if (!$fromStorage) {
  8.                 // unknown error:
  9.                 throw $e;
  10.             }
  11.             // maildirsize file must be missing
  12.
  13.             list($count, $size) = get_quota_from_somewhere_else();
  14.             return array('count' => $count, 'size' => $size);
  15.         }
  16.     }
  17. }
Securing SMTP Transport
Zend_Mail
Zend Framework手册 中文版
Zend_Markup
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Mail
  • 简介
  • 通过SMTP发送邮件
  • 通过一个SMTP连接发送多个邮
  • 使用不同的Transport对象
  • HTML邮件
  • 附件
  • 增加收件人
  • 控制MIME分界线
  • 外加邮件头信息
  • 字符集
  • 编码
  • SMTP 身份验证
  • Securing SMTP Transport
  • Reading Mail Messages


Zend_Markup - Zend Framework Manual

Reading Mail Messages
Zend Framework Reference
Zend Framework手册 中文版
Introduction

Zend_Markup

Table of Contents
  • Introduction
  • Getting Started With Zend_Markup
  • Zend_Markup Parsers
  • Zend_Markup Renderers
Reading Mail Messages
Zend Framework Reference
Zend Framework手册 中文版
Introduction
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


Introduction - Zend Framework Manual

Zend_Markup
Zend_Markup
Zend Framework手册 中文版
Getting Started With Zend_Markup

Introduction

The Zend_Markup component provides an extensible way for parsing text and rendering lightweight markup languages like BBcode and Textile. It is available as of Zend Framework version 1.10.

Zend_Markup uses a factory method to instantiate an instance of a renderer that extends Zend_Markup_Renderer_Abstract. The factory method accepts three arguments. The first one is the parser used to tokenize the text (e.g. BbCode). The second (optional) parameter is the renderer to use, Html by default. Thirdly an array with options to use for the renderer can be specified.

Zend_Markup
Zend_Markup
Zend Framework手册 中文版
Getting Started With Zend_Markup
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Markup
  • Introduction
  • Getting Started With Zend_Markup
  • Zend_Markup Parsers
  • Zend_Markup Renderers


Getting Started With Zend_Markup - Zend Framework Manual

Introduction
Zend_Markup
Zend Framework手册 中文版
Zend_Markup Parsers

Getting Started With Zend_Markup

This guide to get you started with Zend_Markup uses the BBCode parser and HTML renderer. The priciples discussed can be adapted to other parsers and renderers.

Example #1 Basic Zend_Markup Usage

We will first instantiate a Zend_Markup_Renderer_Html object using the Zend_Markup::factory() method. This will also create a Zend_Markup_Parser_Bbcode object which will be added to the renderer object.

Afther that, we will use the render() method to convert a piece of BBCode to HTML.

  1. // Creates instance of Zend_Markup_Renderer_Html,
  2. // with Zend_Markup_Parser_BbCode as its parser
  3. $bbcode = Zend_Markup::factory('Bbcode');
  4.
  5. echo $bbcode->render('[b]bold text[/b] and [i]cursive text[/i]');
  6. // Outputs: '<strong>bold text</strong> and <em>cursive text</em>'

Example #2 A more complicated example of Zend_Markup

This time, we will do exactly the same as above, but with more complicated BBCode markup.

  1. $bbcode = Zend_Markup::factory('Bbcode');
  2.
  3. $input = <<<EOT
  4. [list]
  5. [*]Zend Framework
  6. [*]Foobar
  7. [/list]
  8. EOT;
  9.
  10. echo $bbcode->render($input);
  11. /*
  12. Should output something like:
  13. <ul>
  14. <li>Zend Framework</li>
  15. <li>Foobar</li>
  16. </ul>
  17. */

Example #3 Processing incorrect input

Besides simply parsing and rendering markup such as BBCode, Zend_Markup is also able to handle incorrect input. Most BBCode processors are not able to render all input to XHTML valid output. Zend_Markup corrects input that is nested incorrectly, and also closes tags that were not closed:

  1. $bbcode = Zend_Markup::factory('Bbcode');
  2.
  3. echo $bbcode->render('some [i]wrong [b]sample [/i] text');
  4. // Note that the '[b]' tag is never closed, and is also incorrectly
  5. // nested; regardless, Zend_Markup renders it correctly as:
  6. // some <em>wrong <strong>sample </strong></em><strong> text</strong>
Introduction
Zend_Markup
Zend Framework手册 中文版
Zend_Markup Parsers
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Markup
  • Introduction
  • Getting Started With Zend_Markup
  • Zend_Markup Parsers
  • Zend_Markup Renderers


Zend_Markup Parsers - Zend Framework Manual

Getting Started With Zend_Markup
Zend_Markup
Zend Framework手册 中文版
Zend_Markup Renderers

Zend_Markup Parsers

Zend_Markup is currently shipped with two parsers, a BBCode parser and a Textile parser.

Theory of Parsing

The parsers of Zend_Markup are classes that convert text with markup to a token tree. Although we are using the BBCode parser as example here, the idea of the token tree remains the same across all parsers. We will start with this piece of BBCode for example:

[b]foo[i]bar[/i][/b]baz

Then the BBCode parser will take that value, tear it apart and create the following tree:

  • [b]

    • foo

    • [i]

      • bar

  • baz

You will notice that the closing tags are gone, they don't show up as content in the tree structure. This is because the closing tag isn't part of the actual content. Although, this does not mean that the closing tag is just lost, it is stored inside the tag information for the tag itself. Also, please note that this is just a simplified view of the tree itself. The actual tree contains a lot more information, like the tag's attributes and its name.

The BBCode parser

The BBCode parser is a Zend_Markup parser that converts BBCode to a token tree. The syntax of all BBCode tags is:

  1. [name(=(value|"value"))( attribute=(value|"value"))*]

Some examples of valid BBCode tags are:

[b]
[list=1]
[code file=Zend/Markup.php]
[url="http://framework.zend.com/" title="Zend Framework!"]

By default, all tags are closed by using the format '[/tagname]'.

The Textile parser

The Textile parser is a Zend_Markup parser that converts Textile to a token tree. Because Textile doesn't have a tag structure, the following is a list of example tags:

List of basic Textile tags
Sample input | Sample output
*foo* | <strong>foo</strong>
_foo_ | <em>foo</em>
??foo?? | <cite>foo</cite>
-foo- | <del>foo</del>
+foo+ | <ins>foo</ins>
^foo^ | <sup>foo</sup>
~foo~ | <sub>foo</sub>
%foo% | <span>foo</span>
PHP(PHP Hypertext Preprocessor) | <acronym title="PHP Hypertext Preprocessor">PHP</acronym>
"Zend Framework":http://framework.zend.com/ | <a href="http://framework.zend.com/">Zend Framework</a>
h1. foobar | <h1>foobar</h1>
h6. foobar | <h6>foobar</h6>
!http://framework.zend.com/images/logo.gif! | <img src="http://framework.zend.com/images/logo.gif" />

Also, the Textile parser wraps all tags into paragraphs; a paragraph ends with two newlines, and if there are more tags, a new paragraph will be added.

Lists

The Textile parser also supports two types of lists. The numeric type, using the "#" character and bullit-lists using the "*" character. An example of both lists:

# Item 1
# Item 2

* Item 1
* Item 2

The above will generate two lists: the first, numbered; and the second, bulleted. Inside list items, you can use normal tags like strong (*), and emphasized (_). Tags that need to start on a new line (like 'h1' etc.) cannot be used inside lists.

Getting Started With Zend_Markup
Zend_Markup
Zend Framework手册 中文版
Zend_Markup Renderers
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Markup
  • Introduction
  • Getting Started With Zend_Markup
  • Zend_Markup Parsers
  • Zend_Markup Renderers


Zend_Markup Renderers - Zend Framework Manual

Zend_Markup Parsers
Zend_Markup
Zend Framework手册 中文版
Zend_Measure

Zend_Markup Renderers

Zend_Markup is currently shipped with one renderer, the HTML renderer.

Adding your own tags

By adding your own tags, you can add your own functionality to the Zend_Markup renderers. With the tag structure, you can add about any functionality you want. From simple tags, to complicated tag structures. A simple example for a 'foo' tag:

  1. // Creates instance of Zend_Markup_Renderer_Html,
  2. // with Zend_Markup_Parser_BbCode as its parser
  3. $bbcode = Zend_Markup::factory('Bbcode');
  4.
  5. // this will create a simple 'foo' tag
  6. // The first parameter defines the tag's name.
  7. // The second parameter takes an integer that defines the tags type.
  8. // The third parameter is an array that defines other things about a
  9. // tag, like the tag's group, and (in this case) a start and end tag.
  10. $bbcode->addTag(
  11.     'foo',
  12.     Zend_Markup_Renderer_RendererAbstract::TYPE_REPLACE,
  13.     array(
  14.         'start' => '-bar-',
  15.         'end'   => '-baz-',
  16.         'group' => 'inline'
  17.     )
  18. );
  19.
  20. // now, this will output: 'my -bar-tag-baz-'
  21. echo $bbcode->render('my [foo]tag[/foo]');

Please note that creating your own tags only makes sense when your parser also supports it with a tag structure. Currently, only BBCode supports this. Textile doesn't have support for custom tags.

Some renderers (like the HTML renderer) also have support for a 'tag' parameter. This replaces the 'start' and 'end' parameters, and it renders the tags including some default attributes and the closing tag.

Add a callback tag

By adding a callback tag, you can do a lot more then just a simple replace of the tags. For instance, you can change the contents, use the parameters to influence the output etc.

A callback is a class that implements the Zend_Markup_Renderer_TokenInterface interface. An example of a callback class:

  1. class My_Markup_Renderer_Html_Upper extends Zend_Markup_Renderer_TokenConverterInterface
  2. {
  3.
  4.     public function convert(Zend_Markup_Token $token, $text)
  5.     {
  6.         return '!up!' . strtoupper($text) . '!up!';
  7.     }
  8.
  9. }

Now you can add the 'upper' tag, with as callback, an instance of the My_Markup_Renderer_Html_Upper class. A simple example:

  1. // Creates instance of Zend_Markup_Renderer_Html,
  2. // with Zend_Markup_Parser_BbCode as its parser
  3. $bbcode = Zend_Markup::factory('Bbcode');
  4.
  5. // this will create a simple 'foo' tag
  6. // The first parameter defines the tag's name.
  7. // The second parameter takes an integer that defines the tags type.
  8. // The third parameter is an array that defines other things about a
  9. // tag, like the tag's group, and (in this case) a start and end tag.
  10. $bbcode->addTag(
  11.     'upper',
  12.     Zend_Markup_Renderer_RendererAbstract::TYPE_REPLACE,
  13.     array(
  14.         'callback' => new My_Markup_Renderer_Html_Upper(),
  15.         'group'    => 'inline'
  16.     )
  17. );
  18.
  19. // now, this will output: 'my !up!TAG!up!'
  20. echo $bbcode->render('my [upper]tag[/upper]');

List of tags

List of tags
Sample input (bbcode) | Sample output
[b]foo[/b] | <strong>foo</strong>
[i]foo[/i] | <em>foo</em>
[cite]foo[/cite] | <cite>foo</cite>
[del]foo[/del] | <del>foo</del>
[ins]foo[/ins] | <ins>foo</ins>
[sup]foo[/sup] | <sup>foo</sup>
[sub]foo[/sub] | <sub>foo</sub>
[span]foo[/span] | <span>foo</span>
[acronym title="PHP Hypertext Preprocessor]PHP[/acronym] | <acronym title="PHP Hypertext Preprocessor">PHP</acronym>
[url=http://framework.zend.com/]Zend Framework[/url] | <a href="http://framework.zend.com/">Zend Framework</a>
[h1]foobar[/h1] | <h1>foobar</h1>
[img]http://framework.zend.com/images/logo.gif[/img] | <img src="http://framework.zend.com/images/logo.gif" />
Zend_Markup Parsers
Zend_Markup
Zend Framework手册 中文版
Zend_Measure
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Markup
  • Introduction
  • Getting Started With Zend_Markup
  • Zend_Markup Parsers
  • Zend_Markup Renderers


Zend_Measure - Zend Framework Manual

Zend_Markup Renderers
Zend Framework Reference
Zend Framework手册 中文版
Introduction

Zend_Measure

Table of Contents
  • Introduction
  • Creation of Measurements
  • Outputting measurements
  • Manipulating Measurements
  • Types of measurements
Zend_Markup Renderers
Zend Framework Reference
Zend Framework手册 中文版
Introduction
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


Introduction - Zend Framework Manual

Zend_Measure
Zend_Measure
Zend Framework手册 中文版
Creation of Measurements

Introduction

Zend_Measure_* classes provide a generic and easy way for working with measurements. Using Zend_Measure_* classes, you can convert measurements into different units of the same type. They can be added, subtracted and compared against each other. From a given input made in the user's native language, the unit of measurement can be automatically extracted. Numerous units of measurement are supported.

Example #1 Converting measurements

The following introductory example shows automatic conversion of units of measurement. To convert a measurement, its value and its type have to be known. The value can be an integer, a float, or even a string containing a number. Conversions are only possible for units of the same type (mass, area, temperature, velocity, etc.), not between types.

  1. $locale = new Zend_Locale('en');
  2. $unit = new Zend_Measure_Length(100, Zend_Measure_Length::METER, $locale);
  3.
  4. // Convert meters to yards
  5. echo $unit->convertTo(Zend_Measure_Length::YARD);

Zend_Measure_* includes support for many different units of measurement. The units of measurement all have a unified notation: Zend_Measure_<TYPE>::NAME_OF_UNIT, where <TYPE> corresponds to a well-known physical or numerical property. . Every unit of measurement consists of a conversion factor and a display unit. A detailed list can be found in the chapter Types of measurements .

Example #2 The meter measurement

The meter is used for measuring lengths, so its type constant can be found in the Length class. To refer to this unit of measurement, the notation Length::METER must be used. The display unit is m.

  1. echo Zend_Measure_Length::STANDARD;  // outputs 'Length::METER'
  2. echo Zend_Measure_Length::KILOMETER; // outputs 'Length::KILOMETER'
  3.
  4. $unit = new Zend_Measure_Length(100,'METER');
  5. echo $unit;
  6. // outputs '100 m'
Zend_Measure
Zend_Measure
Zend Framework手册 中文版
Creation of Measurements
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Measure
  • Introduction
  • Creation of Measurements
  • Outputting measurements
  • Manipulating Measurements
  • Types of measurements


Creation of Measurements - Zend Framework Manual

Introduction
Zend_Measure
Zend Framework手册 中文版
Outputting measurements

Creation of Measurements

When creating a measurement object, Zend_Measure_* methods expect the input/original measurement data value as the first parameter. This can be a numeric argument , a String without units, or a localized string with unit(s) specified. The second parameter defines the type of the measurement. Both parameters are mandatory. The language may optionally be specified as the third parameter.

Creating measurements from integers and floats

In addition to integer data values, floating point types may be used, but » "simple decimal fractions like 0.1 or 0.7 cannot be converted into their internal binary counterparts without a little loss of precision," sometimes giving surprising results. Also, do not compare two "float" type numbers for equality.

Example #1 Creation using integer and floating values

  1. $measurement = 1234.7;
  2. $unit = new Zend_Measure_Length((integer)$measurement,
  3.                                 Zend_Measure_Length::STANDARD);
  4. echo $unit;
  5. // outputs '1234 m' (meters)
  6.
  7. $unit = new Zend_Measure_Length($measurement, Zend_Measure_Length::STANDARD);
  8. echo $unit;
  9. // outputs '1234.7 m' (meters)

Creating measurements from strings

Many measurements received as input to Zend Framework applications can only be passed to Zend_Measure_* classes as strings, such as numbers written using » roman numerals or extremely large binary values that exceed the precision of PHP's native integer and float types. Since integers can be denoted using strings, if there is any risk of losing precision due to limitations of PHP's native integer and float types, using strings instead. Zend_Measure_Number uses the BCMath extension to support arbitrary precision, as shown in the example below, to avoid limitations in many PHP functions, such as » bin2dec().

Example #2 Creation using strings

  1. $mystring = "10010100111010111010100001011011101010001";
  2. $unit = new Zend_Measure_Number($mystring, Zend_Measure_Number::BINARY);
  3.
  4. echo $unit;

Usually, Zend_Measure_* can automatically extract the desired measurement embedded in an arbitrary string. Only the first identifiable number denoted using standard European/Latin digits (0,1,2,3,4,5,6,7,8,9) will be used for measurement creation. If there are more numerals later in the string, the rest of these numerals will be ignored.

Example #3 Arbitrary text input containing measurements

  1. $mystring = "My house is 125m² in size";
  2. $unit = new Zend_Measure_Area($mystring, Zend_Measure_Area::STANDARD);
  3. echo $unit; // outputs "125 m²in size";
  4.
  5. $mystring = "My house is 125m² in size, it has 5 rooms of 25m² each.";
  6. $unit = new Zend_Measure_Area($mystring, Zend_Measure_Area::STANDARD);
  7. echo $unit; // outputs "125 m² in size";

Measurements from localized strings

When a string is entered in a localized notation, the correct interpretation can not be determined without knowing the intended locale. The division of decimal digits with "." and grouping of thousands with "," is common in the English language, but not so in other languages. For example, the English number "1,234.50" would be interpreted as meaning "1.2345" in German. To deal with such problems, the locale-aware Zend_Measure_* family of classes offer the possibility to specify a language or region to disambiguate the input data and properly interpret the intended semantic value.

Example #4 Localized string

  1. $locale = new Zend_Locale('de');
  2. $mystring = "The boat is 1,234.50 long.";
  3. $unit = new Zend_Measure_Length($mystring,
  4.                                 Zend_Measure_Length::STANDARD,
  5.                                 $locale);
  6. echo $unit; // outputs "1.234 m"
  7.
  8. $mystring = "The boat is 1,234.50 long.";
  9. $unit = new Zend_Measure_Length($mystring,
  10.                                 Zend_Measure_Length::STANDARD,
  11.                                 'en_US');
  12. echo $unit; // outputs "1234.50 m"

Since Zend Framework 1.7.0 Zend_Measure does also support the usage of an application wide locale. You can simply set a Zend_Locale instance to the registry like shown below. With this notation you can forget about setting the locale manually with each instance when you want to use the same locale multiple times.

  1. // in your bootstrap file
  2. $locale = new Zend_Locale('de_AT');
  3. Zend_Registry::set('Zend_Locale', $locale);
  4.
  5. // somewhere in your application
  6. $length = new Zend_Measure_Length(Zend_Measure_Length::METER();
Introduction
Zend_Measure
Zend Framework手册 中文版
Outputting measurements
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Measure
  • Introduction
  • Creation of Measurements
  • Outputting measurements
  • Manipulating Measurements
  • Types of measurements


Outputting measurements - Zend Framework Manual

Creation of Measurements
Zend_Measure
Zend Framework手册 中文版
Manipulating Measurements

Outputting measurements

Measurements can be output in a number of different ways.

Automatic output

Outputting values

Output with unit of measurement

Output as localized string

Automatic output

Zend_Measure supports outputting of strings automatically.

Example #1 Automatic output

  1. $locale = new Zend_Locale('de');
  2. $mystring = "1.234.567,89 Meter";
  3. $unit = new Zend_Measure_Length($mystring,
  4.                                 Zend_Measure_Length::STANDARD,
  5.                                 $locale);
  6.
  7. echo $unit;

Note: Measurement output
 Output can be achieved simply by using » echo or » print .

Outputting values

The value of a measurement can be output using getValue().

Example #2 Output a value

  1. $locale = new Zend_Locale('de');
  2. $mystring = "1.234.567,89 Meter";
  3. $unit = new Zend_Measure_Length($mystring,
  4.                                 Zend_Measure_Length::STANDARD,
  5.                                 $locale);
  6.
  7. echo $unit->getValue();

The getValue() method accepts an optional parameter 'round' which allows to define a precision for the generated output. The standard precision is '2'.

Output with unit of measurement

The function getType() returns the current unit of measurement.

Example #3 Outputting units

  1. $locale = new Zend_Locale('de');
  2. $mystring = "1.234.567,89";
  3. $unit = new Zend_Measure_Weight($mystring,
  4.                                 Zend_Measure_Weight::POUND,
  5.                                 $locale);
  6.
  7. echo $unit->getType();

Output as localized string

Outputting a string in a format common in the users' country is usually desirable. For example, the measurement "1234567.8" would become "1.234.567,8" for Germany. This functionality will be supported in a future release.

Creation of Measurements
Zend_Measure
Zend Framework手册 中文版
Manipulating Measurements
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Measure
  • Introduction
  • Creation of Measurements
  • Outputting measurements
  • Manipulating Measurements
  • Types of measurements


Manipulating Measurements - Zend Framework Manual

Outputting measurements
Zend_Measure
Zend Framework手册 中文版
Types of measurements

Manipulating Measurements

Parsing and normalization of input, combined with output to localized notations makes data accessible to users in different locales. Many additional methods exist in Zend_Measure_* components to manipulate and work with this data, after it has been normalized.

  • Convert

  • Add and subtract

  • Compare to boolean

  • Compare to greater/smaller

  • Manually change values

  • Manually change types

Convert

Probably the most important feature is the conversion into different units of measurement. The conversion of a unit can be done any number of times using the method convertTo(). Units of measurement can only be converted to other units of the same type (class). Therefore, it is not possible to convert (e.g.) a length into a weight, which would might encourage poor programming practices and allow errors to propagate without exceptions.

The convertTo method accepts an optional parameter. With this parameter you can define an precision for the returned output. The standard precision is '2'.

Example #1 Convert

  1. $locale = new Zend_Locale('de');
  2. $mystring = "1.234.567,89";
  3. $unit = new Zend_Measure_Weight($mystring,'POND', $locale);
  4.
  5. print "Kilo:".$unit->convertTo('KILOGRAM');
  6.
  7. // constants are considered "better practice" than strings
  8. print "Ton:".$unit->convertTo(Zend_Measure_Weight::TON);
  9.
  10. // define a precision for the output
  11. print "Ton:".$unit->convertTo(Zend_Measure_Weight::TON, 3);

Add and subtract

Measurements can be added together using add() and subtracted using sub(). Each addition will create a new object for the result. The actual object will never be changed by the class. The new object will be of the same type as the originating object. Dynamic objects support a fluid style of programming, where complex sequences of operations can be nested without risk of side-effects altering the input objects.

Example #2 Adding units

  1. // Define objects
  2. $unit = new Zend_Measure_Length(200, Zend_Measure_Length::CENTIMETER);
  3. $unit2 = new Zend_Measure_Length(1, Zend_Measure_Length::METER);
  4.
  5. // Add $unit2 to $unit
  6. $sum = $unit->add($unit2);
  7.
  8. echo $sum; // outputs "300 cm"

Note: Automatic conversion
 Adding one object to another will automatically convert it to the correct unit. It is not necessary to call convertTo() before adding different units.

Example #3 Subtract

Subtraction of measurements works just like addition.

  1. // Define objects
  2. $unit = new Zend_Measure_Length(200, Zend_Measure_Length::CENTIMETER);
  3. $unit2 = new Zend_Measure_Length(1, Zend_Measure_Length::METER);
  4.
  5. // Subtract $unit2 from $unit
  6. $sum = $unit->sub($unit2);
  7.
  8. echo $sum;

Compare

Measurements can also be compared, but without automatic unit conversion. Thus, equals() returns TRUE, only if both the value and the unit of measure are identical.

Example #4 Different measurements

  1. // Define measurements
  2. $unit = new Zend_Measure_Length(100, Zend_Measure_Length::CENTIMETER);
  3. $unit2 = new Zend_Measure_Length(1, Zend_Measure_Length::METER);
  4.
  5. if ($unit->equals($unit2)) {
  6.     print "Both measurements are identical";
  7. } else {
  8.     print "These are different measurements";
  9. }

Example #5 Identical measurements

  1. // Define measurements
  2. $unit = new Zend_Measure_Length(100, Zend_Measure_Length::CENTIMETER);
  3. $unit2 = new Zend_Measure_Length(1, Zend_Measure_Length::METER);
  4.
  5. $unit2->setType(Zend_Measure_Length::CENTIMETER);
  6.
  7. if ($unit->equals($unit2)) {
  8.     print "Both measurements are identical";
  9. } else {
  10.     print "These are different measurements";
  11. }

Compare

To determine if a measurement is less than or greater than another, use compare(), which returns 0, -1 or 1 depending on the difference between the two objects. Identical measurements will return 0. Lesser ones will return a negative, greater ones a positive value.

Example #6 Difference

  1. $unit = new Zend_Measure_Length(100, Zend_Measure_Length::CENTIMETER);
  2. $unit2 = new Zend_Measure_Length(1, Zend_Measure_Length::METER);
  3. $unit3 = new Zend_Measure_Length(1.2, Zend_Measure_Length::METER);
  4.
  5. print "Equal:".$unit2->compare($unit);
  6. print "Lesser:".$unit2->compare($unit3);
  7. print "Greater:".$unit3->compare($unit2);

Manually change values

To change the value of a measurement explicitly, use setValue(). to overwrite the current value. The parameters are the same as the constructor.

Example #7 Changing a value

  1. $locale = new Zend_Locale('de_AT');
  2. $unit = new Zend_Measure_Length(1,Zend_Measure_Length::METER);
  3.
  4. $unit->setValue(1.2);
  5. echo $unit;
  6.
  7. $unit->setValue(1.2, Zend_Measure_Length::KILOMETER);
  8. echo $unit;
  9.
  10. $unit->setValue("1.234,56", Zend_Measure_Length::MILLIMETER,$locale);
  11. echo $unit;

Manually change types

To change the type of a measurement without altering its value use setType().

Example #8 Changing the type

  1. $unit = new Zend_Measure_Length(1,Zend_Measure_Length::METER);
  2. echo $unit; // outputs "1 m"
  3.
  4. $unit->setType(Zend_Measure_Length::KILOMETER);
  5. echo $unit; // outputs "1000 km"
Outputting measurements
Zend_Measure
Zend Framework手册 中文版
Types of measurements
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Measure
  • Introduction
  • Creation of Measurements
  • Outputting measurements
  • Manipulating Measurements
  • Types of measurements


Types of measurements - Zend Framework Manual

Manipulating Measurements
Zend_Measure
Zend Framework手册 中文版
Zend_Memory

Types of measurements

All supported measurement types are listed below, each with an example of the standard usage for such measurements.

List of measurement types
Typ | Class | Standardunit | Description
Acceleration | Zend_Measure_Acceleration | Meter per square second | m/s² | Zend_Measure_Acceleration covers the physical factor of acceleration.
Angle | Zend_Measure_Angle | Radiant | rad | Zend_Measure_Angle covers angular dimensions.
Area | Zend_Measure_Area | Square meter | m² | Zend_Measure_Area covers square measures.
Binary | Zend_Measure_Binary | Byte | b | Zend_Measure_Binary covers binary conversions.
Capacitance | Zend_Measure_Capacitance | Farad | F | Zend_Measure_Capacitance covers physical factor of capacitance.
Cooking volumes | Zend_Measure_Cooking_Volume | Cubic meter | m³ | Zend_Measure_Cooking_Volume covers volumes which are used for cooking or written in cookbooks.
Cooking weights | Zend_Measure_Cooking_Weight | Gram | g | Zend_Measure_Cooking_Weight covers the weights which are used for cooking or written in cookbooks.
Current | Zend_Measure_Current | Ampere | A | Zend_Measure_Current covers the physical factor of current.
Density | Zend_Measure_Density | Kilogram per cubic meter | kg/m³ | Zend_Measure_Density covers the physical factor of density.
Energy | Zend_Measure_Energy | Joule | J | Zend_Measure_Energy covers the physical factor of energy.
Force | Zend_Measure_Force | Newton | N | Zend_Measure_Force covers the physical factor of force.
Flow (mass) | Zend_Measure_Flow_Mass | Kilogram per second | kg/s | Zend_Measure_Flow_Mass covers the physical factor of flow rate. The weight of the flowing mass is used as reference point within this class.
Flow (mole) | Zend_Measure_Flow_Mole | Mole per second | mol/s | Zend_Measure_Flow_Mole covers the physical factor of flow rate. The density of the flowing mass is used as reference point within this class.
Flow (volume) | Zend_Measure_Flow_Volume | Cubic meter per second | m³/s | Zend_Measure_Flow_Volume covers the physical factor of flow rate. The volume of the flowing mass is used as reference point within this class.
Frequency | Zend_Measure_Frequency | Hertz | Hz | Zend_Measure_Frequency covers the physical factor of frequency.
Illumination | Zend_Measure_Illumination | Lux | lx | Zend_Measure_Illumination covers the physical factor of light density.
Length | Zend_Measure_Length | Meter | m | Zend_Measure_Length covers the physical factor of length.
Lightness | Zend_Measure_Lightness | Candela per square meter | cd/m² | Zend_Measure_Ligntness covers the physical factor of light energy.
Number | Zend_Measure_Number | Decimal | (10) | Zend_Measure_Number converts between number formats.
Power | Zend_Measure_Power | Watt | W | Zend_Measure_Power covers the physical factor of power.
Pressure | Zend_Measure_Pressure | Newton per square meter | N/m² | Zend_Measure_Pressure covers the physical factor of pressure.
Speed | Zend_Measure_Speed | Meter per second | m/s | Zend_Measure_Speed covers the physical factor of speed.
Temperature | Zend_Measure_Temperature | Kelvin | K | Zend_Measure_Temperature covers the physical factor of temperature.
Time | Zend_Measure_Time | Second | s | Zend_Measure_Time covers the physical factor of time.
Torque | Zend_Measure_Torque | Newton meter | Nm | Zend_Measure_Torque covers the physical factor of torque.
Viscosity (dynamic) | Zend_Measure_Viscosity_Dynamic | Kilogram per meter second | kg/ms | Zend_Measure_Viscosity_Dynamic covers the physical factor of viscosity. The weight of the fluid is used as reference point within this class.
Viscosity (kinematic) | Zend_Measure_Viscosity_Kinematic | Square meter per second | m²/s | Zend_Measure_Viscosity_Kinematic covers the physical factor of viscosity. The distance of the flown fluid is used as reference point within this class.
Volume | Zend_Measure_Volume | Cubic meter | m³ | Zend_Measure_Volume covers the physical factor of volume (content).
Weight | Zend_Measure_Weight | Kilogram | kg | Zend_Measure_Weight covers the physical factor of weight.

Hints for Zend_Measure_Binary

Some popular binary conventions, include terms like kilo-, mega-, giga, etc. in normal language use imply base 10, such as 1000 or 10³. However, in the binary format for computers these terms have to be seen for a conversion factor of 1024 instead of 1000. To preclude confusions a few years ago the notation BI was introduced. Instead of kilobyte, kibibyte for kilo-binary-byte should be used.

In the class BINARY both notations can be found, such as KILOBYTE = 1024 - binary conputer conversion
KIBIBYTE = 1024 - new notation KILO_BINARY_BYTE = 1024 - new, or the notation, long format
KILOBYTE_SI = 1000 - SI notation for kilo (1000). DVDs for example are marked with the
SI-notation, but almost all harddisks are marked in computer binary notation.

Hints for Zend_Measure_Number

The best known number format is the decimal system. Additionally this class supports the octal system, the hexadecimal system, the binary system, the roman number system and some other less popular systems. Note that only the decimal part of numbers is handled. Any fractional part will be stripped.

Roman numbers

For the roman number system digits greater 4000 are supported. In reality these digits are shown with a crossbeam on top of the digit. As the crossbeam can not be shown within the computer, an underline has to be used instead of it.

  1. $great = '_X';
  2. $locale = new Zend_Locale('en');
  3. $unit = new Zend_Measure_Number($great,Zend_Measure_Number::ROMAN, $locale);
  4.
  5. // convert to the decimal system
  6. echo $unit->convertTo(Zend_Measure_Number::DECIMAL);
Manipulating Measurements
Zend_Measure
Zend Framework手册 中文版
Zend_Memory
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Measure
  • Introduction
  • Creation of Measurements
  • Outputting measurements
  • Manipulating Measurements
  • Types of measurements


Zend_Memory - Zend Framework Manual

Types of measurements
Zend Framework Reference
Zend Framework手册 中文版
概述

Zend_Memory

Table of Contents
  • 概述
  • 内存管理器
  • 内存对象
Types of measurements
Zend Framework Reference
Zend Framework手册 中文版
概述
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


概述 - Zend Framework Manual

Zend_Memory
Zend_Memory
Zend Framework手册 中文版
内存管理器

概述

简介

Zend_Memory组件用于在一个受限制的内存环境下管理数据.

内存对象(内存容器)是由内存管理器按照请求生成并在需要的时候透明地交换/加载的.

例如,如果由于受管理对象的创建或加载导致内存使用量超过你所指定的限制,一些管理对象将被复制到内存以外的缓存存储中. 用这种方法,受管理对象的总内存使用量不会超过强制的限制.

内存管理器使用Zend_Cache backends作为存储提供者

Example #1 使用 Zend_Memory 组件

Zend_Memory::factory() 用指定的后端选项实例化内存管理器对象.

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

for ($count = 0; $count < 10000; $count++) {
    $f = fopen($fileNames[$count], 'rb');
    $data = fread($f, filesize($fileNames[$count]));
    $fclose($f);

    $loadedFiles[] = $memoryManager->create($data);
}

echo $loadedFiles[$index1]->value;

$loadedFiles[$index2]->value = $newValue;

$loadedFiles[$index3]->value[$charIndex] = '_';

操作原理

Zend_Memory 组件操作有如下的概念:

  • 内存管理器

  • 内存容器

  • 锁定的内存对象

  • 可移动的内存对象

内存管理器

内存管理器按照用户应用程序的请求生成内存对象(锁定的或可移动的)并返回已交换到内存容器对象中的那些.

内存容器

内存容器有一个虚拟的或者实际的字符串类型的值. 这个属性包含了在内存对象创建时指定的数据值.

你可以作为对象属性操作这个值属性:

$memObject = $memoryManager->create($data);

echo $memObject->value;

$memObject->value = $newValue;

$memObject->value[$index] = '_';

echo ord($memObject->value[$index1]);

$memObject->value = substr($memObject->value, $start, $length);

Note: 如果你使用的PHP版本小于5.2,使用getRef() 方法而不是直接访问属性值.

锁定的内存

锁定的内存对象总是存储在内存中.存储在锁定内存对象中的数据绝不会被交换到缓存后端中去.

可移动内存

当需要时,可移动内存对象由Zend_Memory透明的交换到缓存后端或则从缓存后端加载.

由于性能的考虑,内存管理器不会交换小于指定大小的内存对象.细节请查看 MinSize

Zend_Memory
Zend_Memory
Zend Framework手册 中文版
内存管理器
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Memory
  • 概述
  • 内存管理器
  • 内存对象


内存管理器 - Zend Framework Manual

概述
Zend_Memory
Zend Framework手册 中文版
内存对象

内存管理器

创建一个内存管理器

你可以使用Zend_Memory::factory($backendName [, $backendOprions]) 方法创建一个新的内存管理器(Zend_Memory_Manager 对象).

第一个参数$backendName是一个字符串,他的名字是ZendCache提供的后端实现之一.

第二个参数$backendOptions是一个可选的后端选项参数.

$backendOptions = array(
    'cache_dir' => './tmp/' // Directory where to put the swapped memory blocks
);

$memoryManager = Zend_Memory::factory('File', $backendOptions);

Zend_Memory使用Zend_Cache backends作为存储提供者.

除了标准的Zend_Cache后端之外,你可以使用特殊名称'None'作为后端名称.

$memoryManager = Zend_Memory::factory('None');

如你是使用'None'作为后端名称,内城管理绝不会交换数据块.这在你知道内存没有做限制, 或则对象的总体大小绝不会超过内存限制的情况下非常有用.

'None' 后端不需要任何特定的后端选项.

管理内存对象

这一节描述了在受管理的内存中创建和销毁对象,和控制内存管理的行为的设置.

创建可移动的对象

使用Zend_Memory_Manager::create([$data]) 方法创建可移动的对象 (对象可以被交换):

$memObject = $memoryManager->create($data);

$data是可选的并且用于初始化对象的值.如果$data参数被省略,默认值为空字符串.

创建锁定的对象

使用Zend_Memory_Manager::createLocked([$data])方法创建锁定的(对象不能被交换)对象:

$memObject = $memoryManager->createLocked($data);

$data是可选的并且用于初始化对象的值.如果$data参数被省略,默认值为空字符串.

销毁对象

当内存对象超出作用域它们被从内存管理器中自动销毁和删除:

function foo()
{
    global $memoryManager, $memList;

    ...

    $memObject1 = $memoryManager->create($data1);
    $memObject2 = $memoryManager->create($data2);
    $memObject3 = $memoryManager->create($data3);

    ...

    $memList[] = $memObject3;

    ...

    unset($memObject2); // $memObject2 is destroyed here

    ...
    // $memObject1 is destroyed here
    // but $memObject3 object is still referenced by $memList and is not destroyed
}

应用和可移动对象和锁定对象.

内存管理器设置

内存限制

内存限制是可以被加载的可移动对象使用的一个字节数量.

如果加载和创建导致内存使用量超出了限制,内存管理将交换其他对象.

你可以使用getMemoryLimit() and setMemoryLimit($newLimit)方法 检索和设置内存限制:

$oldLimit = $memoryManager->getMemoryLimit();  // Get memory limit in bytes
$memoryManager->setMemoryLimit($newLimit);     // Set memory limit in bytes

负值表示'没有限制'.

默认值是在php.ini配置文件中'memory_limit'选项的2/3大小, 否则如果'memory_limit'没有在php.ini中设置则为'没有限制'(-1)

MinSize

可以被内存管理器交换的最小对象大小.内存管理器不会交换小于此设置的对象.这是为了减少交换/加载操作的数量.

你可以分别使用getMinSize() 和 setMinSize($newSize)方法 检索和设置对象的最小大小:

$oldMinSize = $memoryManager->getMinSize();  // Get MinSize in bytes
$memoryManager->setMinSize($newSize);        // Set MinSize limit in bytes

默认的最小大小是16KB(16384字节).

概述
Zend_Memory
Zend Framework手册 中文版
内存对象
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Memory
  • 概述
  • 内存管理器
  • 内存对象


内存对象 - Zend Framework Manual

内存管理器
Zend_Memory
Zend Framework手册 中文版
Zend_Mime

内存对象

可移动的

使用内存管理器的create([$data])方法创建可移动的内存对象:

$memObject = $memoryManager->create($data);

"可移动"意思是这样的对象可以被交换并从内存中卸载,然后当应用程序代码访问该对象时再加载它.

锁定的

使用内存管理器的createLocked([$data])方法创建锁定的内存对象:

$memObject = $memoryManager->createLocked($data);

"锁定的"意思是这样的对象绝不会被交换和从内存中卸载.

锁定的对象和可移动的对象提供相同的接口(Zend_Memory_Container_Interface). 因此锁定的对象可以用于任何地方代替可移动对象.

基于性能的考虑,应用程序或则开发者能决定一些对象应该决不会被交换是非常有用的.

访问锁定的对象更快,应为内存管理器不需要追踪这些对象的变化.

The locked objects class (Zend_Memory_Container_Locked) guarantees virtually the same performance as working with a string variable. The overhead is a single dereference to get the class property. 锁定的对象类(Zend_Memory_Container_Locked)保证了和处理字符串变量差不多的性能.

内存容器 '值' 属性.

使用内存容器(可移动或者锁定)'值'属性操作内存对象数据:

$memObject = $memoryManager->create($data);

echo $memObject->value;

$memObject->value = $newValue;

$memObject->value[$index] = '_';

echo ord($memObject->value[$index1]);

$memObject->value = substr($memObject->value, $start, $length);

访问内存对象数据的一个替代的方法是使用getRef() 方法.该方法在必须用于PHP5.2之前的版本.它还不得不用于其他由于性能原因情况

内存容器接口

内存容器提供下面的方法:

getRef() 方法

public function &getRef();

getRef() 方法返回对象值的引用.

如果此时对象不在内存中,可移动对象从缓存中加载. 如果对象从缓存中加载,并且受管理对象的内存使用量总和超过内存限制,将导致交换.

getRef() 方法 必须 用于访问PHP5.2版本以前的内存对象数据.

追踪数据的变化需要额外的资源.getRef()返回字符串的引用,它直接由用户应用程序改变. 因此好的办法是使用getRef()方法进行值数据处理:

$memObject = $memoryManager->create($data);

$value = &$memObject->getRef();

for ($count = 0; $count < strlen($value); $count++) {
    $char = $value[$count];
    ...
}

touch() 方法

public function touch();

touch() 方法应该和getRef()一起使用.当对象值改变时它会发出信号.

$memObject = $memoryManager->create($data);
...

$value = &$memObject->getRef();

for ($count = 0; $count < strlen($value); $count++) {
    ...
    if ($condition) {
        $value[$count] = $char;
    }
    ...
}

$memObject->touch();

lock() 方法

public function lock();

它用于阻止一些你选择的对象被交换.正常情况,这是不需要的,因为内存管理器使用智能的算法决定候选的交换数据. 但是你明确地知道,在代码的这一部分对象不应该被交换,你可以锁定它们.

在内存中锁定的对象还保证了在解锁对象前getRef()方法返回的引用是有效的:

$memObject1 = $memoryManager->create($data1);
$memObject2 = $memoryManager->create($data2);
...

$memObject1->lock();
$memObject2->lock();

$value1 = &$memObject1->getRef();
$value2 = &$memObject2->getRef();

for ($count = 0; $count < strlen($value2); $count++) {
    $value1 .= $value2[$count];
}

$memObject1->touch();
$memObject1->unlock();
$memObject2->unlock();

unlock() 方法

public function unlock();

当不再需要锁定是unlock() 方法解锁一个内存对象.查看上面的例子.

isLocked() 方法

public function isLocked();

isLocked()方法用于检测是否一个对象被锁定了.如果对象被锁定她返回 true,否则如果没有被锁定返回false. 对于"锁定的"对象这总是true,对于"可移动"对象可以使true 或则false.

内存管理器
Zend_Memory
Zend Framework手册 中文版
Zend_Mime
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Memory
  • 概述
  • 内存管理器
  • 内存对象


Zend_Mime - Zend Framework Manual

内存对象
Zend Framework Reference
Zend Framework手册 中文版
Zend_Mime

Zend_Mime

Table of Contents
  • Zend_Mime
  • Zend_Mime_Message
  • Zend_Mime_Part
内存对象
Zend Framework Reference
Zend Framework手册 中文版
Zend_Mime
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


Zend_Mime - Zend Framework Manual

Zend_Mime
Zend_Mime
Zend Framework手册 中文版
Zend_Mime_Message

Zend_Mime

简介

Zend_Mime是一个用来处理多段MIME消息的辅助类， 在Zend_Mail和Zend_Mime_Message中使用了它， 也可在需要MIME支持的应用程序中使用。

静态方法和常量

Zend_Mime提供了一系列静态辅助方法来处理MIME：

  • Zend_Mime::isPrintable(): 给定的字符串中不含不可打印(unprintable)的字符，则返回TRUE，否则返回FALSE。

  • Zend_Mime::encodeBase64(): 将一个字符串用base64编码。

  • Zend_Mime::encodeQuotedPrintable(): 将一个字符串以quoted-printable机制编码。

Zend_Mime定义了一系列通常在处理MIME消息的时候要用到的常量：

  • Zend_Mime::TYPE_OCTETSTREAM: 'application/octet-stream'

  • Zend_Mime::TYPE_TEXT: 'text/plain'

  • Zend_Mime::TYPE_HTML: 'text/html'

  • Zend_Mime::ENCODING_7BIT: '7bit'

  • Zend_Mime::ENCODING_8BIT: '8bit'

  • Zend_Mime::ENCODING_QUOTEDPRINTABLE: 'quoted-printable'

  • Zend_Mime::ENCODING_BASE64: 'base64'

  • Zend_Mime::DISPOSITION_ATTACHMENT: 'attachment'

  • Zend_Mime::DISPOSITION_INLINE: 'inline'

实例化Zend_Mime

在实例化Zend_Mime 对象时，指定了MIME分界线(MIME boundary)， 在调用下面的非静态函数都会用到它(MIME分界线)。 如果传递给构造函数一个字符串参数，那么这个参数就用来指定MIME分界线； 如果没有给出参数，那么构造器在调用的时候会随机产生一个MIME分界线。

Zend_Mime对象拥有以下方法：

  • boundary(): 返回MIME分界线字符串。

  • boundaryLine(): 返回完整的MIME分界线行。

  • mimeEnd(): 返回完整的MIME结束的分界线行。

Zend_Mime
Zend_Mime
Zend Framework手册 中文版
Zend_Mime_Message
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Mime
  • Zend_Mime
  • Zend_Mime_Message
  • Zend_Mime_Part


Zend_Mime_Message - Zend Framework Manual

Zend_Mime
Zend_Mime
Zend Framework手册 中文版
Zend_Mime_Part

Zend_Mime_Message

简介

Zend_Mime_Message表示一个包含一个或多个段（段以Zend_Mime_Part对象表示）的符合MIME标准的消息。 在Zend_Mime_Message中，符合MIME标准的多段消息由Zend_Mime_Part对象产生。 编码和分段也是在Zend_Mime_Message中被处理。Zend_Mime_Message对象也可从给定的字符串中重构出来（实验性的）。 Zend_Mime_Message也被Zend_Mail使用（译注：Zend_Mail继承了Zend_Mime_Message）。

实例化

Zend_Mime_Message没有构造函数。

增加MIME消息段

Zend_Mime_Message对象通过调用addPart($part)方法， 可以添加Zend_Mime_Part对象。

调用Zend_Mime_Message对象的getParts()方法， 返回Zend_Mime_Part 对象数组。 Zend_Mime_Part对象可以被更改，因为他们以引用的方式存储在Zend_Mime_Message对象的数组中。 如果数组中有新的段加入或者改变了段的顺序，该数组需通过调用setParts($partsArray)方法，反馈到Zend_Mime_Message中去。

当Zend_Mime_Message中存在多个段，方法isMultiPart()将返回TRUE。 Zend_Mime_Message在产生实际输出产生多段的MIME消息。

分界线处理

Zend_Mime_Message通常创建和使用自身的Zend_Mime对象来产生MINE分界线。 如果你想自己定义分界线或想更改Zend_Mime_Message自身的Zend_Mime对象的缺省的行为， 你可以自己实例化Zend_Mime对象，然后通过setMime(Zend_Mime $mime)方法注册到Zend_Mime_Message对象中去，通常你不需要这么做。

->getMime()方法，返回Zend_Mime实例，当generateMessage()被调用时Zend_Mime实例用来渲染MIME消息。

->generateMessage()方法，渲染Zend_Mime_Message的内容为字符串。

解析字符串，创建Zend_Mime_Message对象（实验性的）

给定一个字符串形式的符合MIME标准的消息，可以重构出Zend_Mime_Message对象。 Zend_Mime_Message有一个静态的工厂方法，解析字符串，返回Zend_Mime_Message对象。

Zend_Mime_Message::createFromMessage($str, $boundary)将给定的字符串解码， 返回Zend_Mime_Message对象，可以用getParts()方法来检验一下。

Zend_Mime
Zend_Mime
Zend Framework手册 中文版
Zend_Mime_Part
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Mime
  • Zend_Mime
  • Zend_Mime_Message
  • Zend_Mime_Part


Zend_Mime_Part - Zend Framework Manual

Zend_Mime_Message
Zend_Mime
Zend Framework手册 中文版
Zend_Navigation

Zend_Mime_Part

简介

Zend_Mime_Part表示 MIME 消息的一个段。它包含了MIME消息段的实际内容以及编码、内容类型和原始的文件名等一些附加信息。它也提供了一个方法，用来从存储的数据产生字符串。Zend_Mime_Part对象可以被添加到Zend_Mime_Message中去，来聚合产生一个完整的多段的MIME消息。

实例化

Zend_Mime_Part通过表示段的内容的字符串来实例化。缺省的内容类型为OCTET-STREAM，编码为8Bit。在Zend_Mime_Part实例化之后, 可以直接访问它的属性来设置元信息：

<?php
public $type = ZMime::TYPE_OCTETSTREAM;
public $encoding = ZMime::ENCODING_8BIT;
public $id;
public $disposition;
public $filename;
public $description;
public $charset;

解析（rendering）消息段为字符串的方法

getContent()方法，返回经过编码的消息段字符串，编码方式由属性$encoding指定。有效的编码方式为Zend_Mime::ENCODING_*。字符集的转换还未实现。

getHeaders()方法，返回产自对象公有属性的MIME消息段的消息头。在该方法调用之前，对象的这些共有属性必须被正确的设置。

  • $charset 如果内容为Text类型(纯文本或HTML)，该属性被设置为实际的字符集。

  • $id 可能被设置，用来标识HTML邮件中内嵌图片的content-id。

  • $filename 给出了当文件被下载时的文件名。

  • $disposition 指定了文件是当作附件，还是当作邮件的内嵌资源。

  • $description 只用在提供信息上。

Zend_Mime_Message
Zend_Mime
Zend Framework手册 中文版
Zend_Navigation
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Mime
  • Zend_Mime
  • Zend_Mime_Message
  • Zend_Mime_Part


Zend_Navigation - Zend Framework Manual

Zend_Mime_Part
Zend Framework Reference
Zend Framework手册 中文版
Introduction

Zend_Navigation

Table of Contents
  • Introduction
  • Pages
  • Containers
Zend_Mime_Part
Zend Framework Reference
Zend Framework手册 中文版
Introduction
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


Introduction - Zend Framework Manual

Zend_Navigation
Zend_Navigation
Zend Framework手册 中文版
Pages

Introduction

Zend_Navigation is a component for managing trees of pointers to web pages. Simply put: It can be used for creating menus, breadcrumbs, links, and sitemaps, or serve as a model for other navigation related purposes.

Pages and Containers

There are two main concepts in Zend_Navigation:

Pages

A page (Zend_Navigation_Page) in Zend_Navigation – in its most basic form – is an object that holds a pointer to a web page. In addition to the pointer itself, the page object contains a number of other properties that are typically relevant for navigation, such as label, title, etc.

Read more about pages in the pages section.

Containers

A navigation container (Zend_Navigation_Container) is a container class for pages. It has methods for adding, retrieving, deleting and iterating pages. It implements the » SPL interfaces RecursiveIterator and Countable, and can thus be iterated with SPL iterators such as RecursiveIteratorIterator.

Read more about containers in the containers section.

Note: Zend_Navigation_Page extends Zend_Navigation_Container, which means that a page can have sub pages.

Separation of data (model) and rendering (view)

Classes in the Zend_Navigation namespace do not deal with rendering of navigational elements. Rendering is done with navigational view helpers. However, pages contain information that is used by view helpers when rendering, such as; label, CSS class, title, lastmod and priority properties for sitemaps, etc.

Read more about rendering navigational elements in the manual section on navigation helpers.

Zend_Navigation
Zend_Navigation
Zend Framework手册 中文版
Pages
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Navigation
  • Introduction
  • Pages
  • Containers


Pages - Zend Framework Manual

Introduction
Zend_Navigation
Zend Framework手册 中文版
Containers

Pages

Zend_Navigation ships with two page types:

  • MVC pages – using the class Zend_Navigation_Page_Mvc

  • URI pages – using the class Zend_Navigation_Page_Uri

MVC pages are link to on-site web pages, and are defined using MVC parameters (action, controller, module, route, params). URI pages are defined by a single property uri, which give you the full flexibility to link off-site pages or do other things with the generated links (e.g. an URI that turns into <a href="#">foo<a>).

Common page features

All page classes must extend Zend_Navigation_Page, and will thus share a common set of features and properties. Most notably they share the options in the table below and the same initialization process.

Option keys are mapped to set methods. This means that the option order maps to the method setOrder(), and reset_params maps to the method setResetParams(). If there is no setter method for the option, it will be set as a custom property of the page.

Read more on extending Zend_Navigation_Page in Creating custom page types.

Common page options
Key | Type | Default | Description
label | String | NULL | A page label, such as 'Home' or 'Blog'.
id | String | int | NULL | An id tag/attribute that may be used when rendering the page, typically in an anchor element.
class | String | NULL | A CSS class that may be used when rendering the page, typically in an anchor element.
title | String | NULL | A short page description, typically for using as the title attribute in an anchor.
target | String | NULL | Specifies a target that may be used for the page, typically in an anchor element.
rel | Array | array() | Specifies forward relations for the page. Each element in the array is a key-value pair, where the key designates the relation/link type, and the value is a pointer to the linked page. An example of a key-value pair is 'alternate' => 'format/plain.html'. To allow full flexbility, there are no restrictions on relation values. The value does not have to be a string. Read more about rel and rev in the section on the Links helper..
rev | Array | array() | Specifies reverse relations for the page. Works exactly like rel.
order | String | int | NULL | NULL | Works like order for elements in Zend_Form. If specified, the page will be iterated in a specific order, meaning you can force a page to be iterated before others by setting the order attribute to a low number, e.g. -100. If a String is given, it must parse to a valid int. If NULL is given, it will be reset, meaning the order in which the page was added to the container will be used.
resource | String | Zend_Acl_Resource_Interface | NULL | NULL | ACL resource to associate with the page. Read more in the section on ACL integration in view helpers..
privilege | String | NULL | NULL | ACL privilege to associate with the page. Read more in the section on ACL integration in view helpers..
active | bool | FALSE | Whether the page should be considered active for the current request. If active is FALSE or not given, MVC pages will check its properties against the request object upon calling $page->isActive().
visible | bool | TRUE | Whether page should be visible for the user, or just be a part of the structure. Invisible pages are skipped by view helpers.
pages | Array | Zend_Config | NULL | NULL | Child pages of the page. This could be an Array or Zend_Config object containing either page options that can be passed to the factory() method, or actual Zend_Navigation_Page instances, or a mixture of both.

Note: Custom properties
 All pages support setting and getting of custom properties by use of the magic methods __set($name, $value), __get($name), __isset($name) and __unset($name). Custom properties may have any value, and will be included in the array that is returned from $page->toArray(), which means that pages can be serialized/deserialized successfully even if the pages contains properties that are not native in the page class.
Both native and custom properties can be set using $page->set($name, $value) and retrieved using $page->get($name), or by using magic methods.

Example #1 Custom page properties

This example shows how custom properties can be used.

  1. $page = new Zend_Navigation_Page_Mvc();
  2. $page->foo = 'bar';
  3. $page->meaning = 42;
  4.
  5. echo $page->foo;
  6.
  7. if ($page->meaning != 42) {
  8.     // action should be taken
  9. }

Zend_Navigation_Page_Mvc

MVC pages are defined using MVC parameters known from the Zend_Controller component. An MVC page will use Zend_Controller_Action_Helper_Url internally in the getHref() method to generate hrefs, and the isActive() method will intersect the Zend_Controller_Request_Abstract params with the page's params to determine if the page is active.

MVC page options
Key | Type | Default | Description
action | String | NULL | Action name to use when generating href to the page.
controller | String | NULL | Controller name to use when generating href to the page.
module | String | NULL | Module name to use when generating href to the page.
params | Array | array() | User params to use when generating href to the page.
route | String | NULL | Route name to use when generating href to the page.
reset_params | bool | TRUE | Whether user params should be reset when generating href to the page.

Note: The three examples below assume a default MVC setup with the default route in place.
The URI returned is relative to the baseUrl in Zend_Controller_Front. In the examples, the baseUrl is '/' for simplicity.

Example #2 getHref() generates the page URI

This example show that MVC pages use Zend_Controller_Action_Helper_Url internally to generate URIs when calling $page->getHref().

  1. // getHref() returns /
  2. $page = new Zend_Navigation_Page_Mvc(array(
  3.     'action'     => 'index',
  4.     'controller' => 'index'
  5. ));
  6.
  7. // getHref() returns /blog/post/view
  8. $page = new Zend_Navigation_Page_Mvc(array(
  9.     'action'     => 'view',
  10.     'controller' => 'post',
  11.     'module'     => 'blog'
  12. ));
  13.
  14. // getHref() returns /blog/post/view/id/1337
  15. $page = new Zend_Navigation_Page_Mvc(array(
  16.     'action'     => 'view',
  17.     'controller' => 'post',
  18.     'module'     => 'blog',
  19.     'params'     => array('id' => 1337)
  20. ));

Example #3 isActive() determines if page is active

This example show that MVC pages determine whether they are active by using the params found in the request object.

  1. /*
  2. * Dispatched request:
  3. * - module:     default
  4. * - controller: index
  5. * - action:     index
  6. */
  7. $page1 = new Zend_Navigation_Page_Mvc(array(
  8.     'action'     => 'index',
  9.     'controller' => 'index'
  10. ));
  11.
  12. $page2 = new Zend_Navigation_Page_Mvc(array(
  13.     'action'     => 'bar',
  14.     'controller' => 'index'
  15. ));
  16.
  17. $page1->isActive(); // returns true
  18. $page2->isActive(); // returns false
  19.
  20. /*
  21. * Dispatched request:
  22. * - module:     blog
  23. * - controller: post
  24. * - action:     view
  25. * - id:         1337
  26. */
  27. $page = new Zend_Navigation_Page_Mvc(array(
  28.     'action'     => 'view',
  29.     'controller' => 'post',
  30.     'module'     => 'blog'
  31. ));
  32.
  33. // returns true, because request has the same module, controller and action
  34. $page->isActive();
  35.
  36. /*
  37. * Dispatched request:
  38. * - module:     blog
  39. * - controller: post
  40. * - action:     view
  41. */
  42. $page = new Zend_Navigation_Page_Mvc(array(
  43.     'action'     => 'view',
  44.     'controller' => 'post',
  45.     'module'     => 'blog',
  46.     'params'     => array('id' => null)
  47. ));
  48.
  49. // returns false, because page requires the id param to be set in the request
  50. $page->isActive(); // returns false

Example #4 Using routes

Routes can be used with MVC pages. If a page has a route, this route will be used in getHref() to generate the URL for the page.

Note: Note that when using the route property in a page, you should also specify the default params that the route defines (module, controller, action, etc.), otherwise the isActive() method will not be able to determine if the page is active. The reason for this is that there is currently no way to get the default params from a Zend_Controller_Router_Route_Interface object, nor to retrieve the current route from a Zend_Controller_Router_Interface object.

  1. // the following route is added to the ZF router
  2. Zend_Controller_Front::getInstance()->getRouter()->addRoute(
  3.     'article_view', // route name
  4.     new Zend_Controller_Router_Route(
  5.         'a/:id',
  6.         array(
  7.             'module'     => 'news',
  8.             'controller' => 'article',
  9.             'action'     => 'view',
  10.             'id'         => null
  11.         )
  12.     )
  13. );
  14.
  15. // a page is created with a 'route' option
  16. $page = new Zend_Navigation_Page_Mvc(array(
  17.     'label'      => 'A news article',
  18.     'route'      => 'article_view',
  19.     'module'     => 'news',    // required for isActive(), see note above
  20.     'controller' => 'article', // required for isActive(), see note above
  21.     'action'     => 'view',    // required for isActive(), see note above
  22.     'params'     => array('id' => 42)
  23. ));
  24.
  25. // returns: /a/42
  26. $page->getHref();

Zend_Navigation_Page_Uri

Pages of type Zend_Navigation_Page_Uri can be used to link to pages on other domains or sites, or to implement custom logic for the page. URI pages are simple; in addition to the common page options, a URI page takes only one option — uri. The uri will be returned when calling $page->getHref(), and may be a String or NULL.

Note: Zend_Navigation_Page_Uri will not try to determine whether it should be active when calling $page->isActive(). It merely returns what currently is set, so to make a URI page active you have to manually call $page->setActive() or specifying active as a page option when constructing.

URI page options
Key | Type | Default | Description
uri | String | NULL | URI to page. This can be any string or NULL.

Creating custom page types

When extending Zend_Navigation_Page, there is usually no need to override the constructor or the methods setOptions() or setConfig(). The page constructor takes a single parameter, an Array or a Zend_Config object, which is passed to setOptions() or setConfig() respectively. Those methods will in turn call set() method, which will map options to native or custom properties. If the option internal_id is given, the method will first look for a method named setInternalId(), and pass the option to this method if it exists. If the method does not exist, the option will be set as a custom property of the page, and be accessible via $internalId = $page->internal_id; or $internalId = $page->get('internal_id');.

Example #5 The most simple custom page

The only thing a custom page class needs to implement is the getHref() method.

  1. class My_Simple_Page extends Zend_Navigation_Page
  2. {
  3.     public function getHref()
  4.     {
  5.         return 'something-completely-different';
  6.     }
  7. }

Example #6 A custom page with properties

When adding properties to an extended page, there is no need to override/modify setOptions() or setConfig().

  1. class My_Navigation_Page extends Zend_Navigation_Page
  2. {
  3.     private $_foo;
  4.     private $_fooBar;
  5.
  6.     public function setFoo($foo)
  7.     {
  8.         $this->_foo = $foo;
  9.     }
  10.
  11.     public function getFoo()
  12.     {
  13.         return $this->_foo;
  14.     }
  15.
  16.     public function setFooBar($fooBar)
  17.     {
  18.         $this->_fooBar = $fooBar;
  19.     }
  20.
  21.     public function getFooBar()
  22.     {
  23.         return $this->_fooBar;
  24.     }
  25.
  26.     public function getHref()
  27.     {
  28.         return $this->foo . '/' . $this->fooBar;
  29.     }
  30. }
  31.
  32. // can now construct using
  33. $page = new My_Navigation_Page(array(
  34.     'label'   => 'Property names are mapped to setters',
  35.     'foo'     => 'bar',
  36.     'foo_bar' => 'baz'
  37. ));
  38.
  39. // ...or
  40. $page = Zend_Navigation_Page::factory(array(
  41.     'type'    => 'My_Navigation_Page',
  42.     'label'   => 'Property names are mapped to setters',
  43.     'foo'     => 'bar',
  44.     'foo_bar' => 'baz'
  45. ));

Creating pages using the page factory

All pages (also custom classes), can be created using the page factory, Zend_Navigation_Page::factory(). The factory can take an array with options, or a Zend_Config object. Each key in the array/config corresponds to a page option, as seen in the section on Pages. If the option uri is given and no MVC options are given (action, controller, module, route), an URI page will be created. If any of the MVC options are given, an MVC page will be created.

If type is given, the factory will assume the value to be the name of the class that should be created. If the value is mvc or uri and MVC/URI page will be created.

Example #7 Creating an MVC page using the page factory

  1. $page = Zend_Navigation_Page::factory(array(
  2.     'label'  => 'My MVC page',
  3.     'action' => 'index'
  4. ));
  5.
  6. $page = Zend_Navigation_Page::factory(array(
  7.     'label'      => 'Search blog',
  8.     'action'     => 'index',
  9.     'controller' => 'search',
  10.     'module'     => 'blog'
  11. ));
  12.
  13. $page = Zend_Navigation_Page::factory(array(
  14.     'label'      => 'Home',
  15.     'action'     => 'index',
  16.     'controller' => 'index',
  17.     'module'     => 'index',
  18.     'route'      => 'home'
  19. ));
  20.
  21. $page = Zend_Navigation_Page::factory(array(
  22.     'type'   => 'mvc',
  23.     'label'  => 'My MVC page'
  24. ));

Example #8 Creating a URI page using the page factory

  1. $page = Zend_Navigation_Page::factory(array(
  2.     'label' => 'My URI page',
  3.     'uri'   => 'http://www.example.com/'
  4. ));
  5.
  6. $page = Zend_Navigation_Page::factory(array(
  7.     'label'  => 'Search',
  8.     'uri'    => 'http://www.example.com/search',
  9.     'active' => true
  10. ));
  11.
  12. $page = Zend_Navigation_Page::factory(array(
  13.     'label' => 'My URI page',
  14.     'uri'   => '#'
  15. ));
  16.
  17. $page = Zend_Navigation_Page::factory(array(
  18.     'type'   => 'uri',
  19.     'label'  => 'My URI page'
  20. ));

Example #9 Creating a custom page type using the page factory

To create a custom page type using the factory, use the option type to specify a class name to instantiate.

  1. class My_Navigation_Page extends Zend_Navigation_Page
  2. {
  3.     protected $_fooBar = 'ok';
  4.
  5.     public function setFooBar($fooBar)
  6.     {
  7.         $this->_fooBar = $fooBar;
  8.     }
  9. }
  10.
  11. $page = Zend_Navigation_Page::factory(array(
  12.     'type'    => 'My_Navigation_Page',
  13.     'label'   => 'My custom page',
  14.     'foo_bar' => 'foo bar'
  15. ));
Introduction
Zend_Navigation
Zend Framework手册 中文版
Containers
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Navigation
  • Introduction
  • Pages
  • Containers


Containers - Zend Framework Manual

Pages
Zend_Navigation
Zend Framework手册 中文版
Zend_Oauth

Containers

Containers have methods for adding, retrieving, deleting and iterating pages. Containers implement the » SPL interfaces RecursiveIterator and Countable, meaning that a container can be iterated using the SPL RecursiveIteratorIterator class.

Creating containers

Zend_Navigation_Container is abstract, and can not be instantiated directly. Use Zend_Navigation if you want to instantiate a container.

Zend_Navigation can be constructed entirely empty, or take an array or a Zend_Config object with pages to put in the container. Each page in the given array/config will eventually be passed to the addPage() method of the container class, which means that each element in the array/config can be an array or a config object, or a Zend_Navigation_Page instance.

Example #1 Creating a container using an array

  1. /*
  2. * Create a container from an array
  3. *
  4. * Each element in the array will be passed to
  5. * Zend_Navigation_Page::factory() when constructing.
  6. */
  7. $container = new Zend_Navigation(array(
  8.     array(
  9.         'label' => 'Page 1',
  10.         'id' => 'home-link',
  11.         'uri' => '/'
  12.     ),
  13.     array(
  14.         'label' => 'Zend',
  15.         'uri' => 'http://www.zend-project.com/',
  16.         'order' => 100
  17.     ),
  18.     array(
  19.         'label' => 'Page 2',
  20.         'controller' => 'page2',
  21.         'pages' => array(
  22.             array(
  23.                 'label' => 'Page 2.1',
  24.                 'action' => 'page2_1',
  25.                 'controller' => 'page2',
  26.                 'class' => 'special-one',
  27.                 'title' => 'This element has a special class',
  28.                 'active' => true
  29.             ),
  30.             array(
  31.                 'label' => 'Page 2.2',
  32.                 'action' => 'page2_2',
  33.                 'controller' => 'page2',
  34.                 'class' => 'special-two',
  35.                 'title' => 'This element has a special class too'
  36.             )
  37.         )
  38.     ),
  39.     array(
  40.         'label' => 'Page 2 with params',
  41.         'action' => 'index',
  42.         'controller' => 'page2',
  43.         // specify a param or two
  44.         'params' => array(
  45.             'format' => 'json',
  46.             'foo' => 'bar'
  47.         )
  48.     ),
  49.     array(
  50.         'label' => 'Page 2 with params and a route',
  51.         'action' => 'index',
  52.         'controller' => 'page2',
  53.         // specify a route name and a param for the route
  54.         'route' => 'nav-route-example',
  55.         'params' => array(
  56.             'format' => 'json'
  57.         )
  58.     ),
  59.     array(
  60.         'label' => 'Page 3',
  61.         'action' => 'index',
  62.         'controller' => 'index',
  63.         'module' => 'mymodule',
  64.         'reset_params' => false
  65.     ),
  66.     array(
  67.         'label' => 'Page 4',
  68.         'uri' => '#',
  69.         'pages' => array(
  70.             array(
  71.                 'label' => 'Page 4.1',
  72.                 'uri' => '/page4',
  73.                 'title' => 'Page 4 using uri',
  74.                 'pages' => array(
  75.                     array(
  76.                         'label' => 'Page 4.1.1',
  77.                         'title' => 'Page 4 using mvc params',
  78.                         'action' => 'index',
  79.                         'controller' => 'page4',
  80.                         // let's say this page is active
  81.                         'active' => '1'
  82.                     )
  83.                 )
  84.             )
  85.         )
  86.     ),
  87.     array(
  88.         'label' => 'Page 0?',
  89.         'uri' => '/setting/the/order/option',
  90.         // setting order to -1 should make it appear first
  91.         'order' => -1
  92.     ),
  93.     array(
  94.         'label' => 'Page 5',
  95.         'uri' => '/',
  96.         // this page should not be visible
  97.         'visible' => false,
  98.         'pages' => array(
  99.             array(
  100.                 'label' => 'Page 5.1',
  101.                 'uri' => '#',
  102.                 'pages' => array(
  103.                     array(
  104.                         'label' => 'Page 5.1.1',
  105.                         'uri' => '#',
  106.                         'pages' => array(
  107.                             array(
  108.                                 'label' => 'Page 5.1.2',
  109.                                 'uri' => '#',
  110.                                 // let's say this page is active
  111.                                 'active' => true
  112.                             )
  113.                         )
  114.                     )
  115.                 )
  116.             )
  117.         )
  118.     ),
  119.     array(
  120.         'label' => 'ACL page 1 (guest)',
  121.         'uri' => '#acl-guest',
  122.         'resource' => 'nav-guest',
  123.         'pages' => array(
  124.             array(
  125.                 'label' => 'ACL page 1.1 (foo)',
  126.                 'uri' => '#acl-foo',
  127.                 'resource' => 'nav-foo'
  128.             ),
  129.             array(
  130.                 'label' => 'ACL page 1.2 (bar)',
  131.                 'uri' => '#acl-bar',
  132.                 'resource' => 'nav-bar'
  133.             ),
  134.             array(
  135.                 'label' => 'ACL page 1.3 (baz)',
  136.                 'uri' => '#acl-baz',
  137.                 'resource' => 'nav-baz'
  138.             ),
  139.             array(
  140.                 'label' => 'ACL page 1.4 (bat)',
  141.                 'uri' => '#acl-bat',
  142.                 'resource' => 'nav-bat'
  143.             )
  144.         )
  145.     ),
  146.     array(
  147.         'label' => 'ACL page 2 (member)',
  148.         'uri' => '#acl-member',
  149.         'resource' => 'nav-member'
  150.     ),
  151.     array(
  152.         'label' => 'ACL page 3 (admin',
  153.         'uri' => '#acl-admin',
  154.         'resource' => 'nav-admin',
  155.         'pages' => array(
  156.             array(
  157.                 'label' => 'ACL page 3.1 (nothing)',
  158.                 'uri' => '#acl-nada'
  159.             )
  160.         )
  161.     ),
  162.     array(
  163.         'label' => 'Zend Framework',
  164.         'route' => 'zf-route'
  165.     )
  166. ));

Example #2 Creating a container using a config object

  1. /* CONTENTS OF /path/to/navigation.xml:
  2. <?xml version="1.0" encoding="UTF-8"?>
  3. <config>
  4.     <nav>
  5.
  6.         <zend>
  7.             <label>Zend</label>
  8.             <uri>http://www.zend-project.com/</uri>
  9.             <order>100</order>
  10.         </zend>
  11.
  12.         <page1>
  13.             <label>Page 1</label>
  14.             <uri>page1</uri>
  15.             <pages>
  16.
  17.                 <page1_1>
  18.                     <label>Page 1.1</label>
  19.                     <uri>page1/page1_1</uri>
  20.                 </page1_1>
  21.
  22.             </pages>
  23.         </page1>
  24.
  25.         <page2>
  26.             <label>Page 2</label>
  27.             <uri>page2</uri>
  28.             <pages>
  29.
  30.                 <page2_1>
  31.                     <label>Page 2.1</label>
  32.                     <uri>page2/page2_1</uri>
  33.                 </page2_1>
  34.
  35.                 <page2_2>
  36.                     <label>Page 2.2</label>
  37.                     <uri>page2/page2_2</uri>
  38.                     <pages>
  39.
  40.                         <page2_2_1>
  41.                             <label>Page 2.2.1</label>
  42.                             <uri>page2/page2_2/page2_2_1</uri>
  43.                         </page2_2_1>
  44.
  45.                         <page2_2_2>
  46.                             <label>Page 2.2.2</label>
  47.                             <uri>page2/page2_2/page2_2_2</uri>
  48.                             <active>1</active>
  49.                         </page2_2_2>
  50.
  51.                     </pages>
  52.                 </page2_2>
  53.
  54.                 <page2_3>
  55.                     <label>Page 2.3</label>
  56.                     <uri>page2/page2_3</uri>
  57.                     <pages>
  58.
  59.                         <page2_3_1>
  60.                             <label>Page 2.3.1</label>
  61.                             <uri>page2/page2_3/page2_3_1</uri>
  62.                         </page2_3_1>
  63.
  64.                         <page2_3_2>
  65.                             <label>Page 2.3.2</label>
  66.                             <uri>page2/page2_3/page2_3_2</uri>
  67.                             <visible>0</visible>
  68.                             <pages>
  69.
  70.                                     <page2_3_2_1>
  71.                                         <label>Page 2.3.2.1</label>
  72.                                         <uri>page2/page2_3/page2_3_2/1</uri>
  73.                                         <active>1</active>
  74.                                     </page2_3_2_1>
  75.
  76.                                     <page2_3_2_2>
  77.                                         <label>Page 2.3.2.2</label>
  78.                                         <uri>page2/page2_3/page2_3_2/2</uri>
  79.                                         <active>1</active>
  80.
  81.                                         <pages>
  82.                                             <page_2_3_2_2_1>
  83.                                                 <label>Ignore</label>
  84.                                                 <uri>#</uri>
  85.                                                 <active>1</active>
  86.                                             </page_2_3_2_2_1>
  87.                                         </pages>
  88.                                     </page2_3_2_2>
  89.
  90.                             </pages>
  91.                         </page2_3_2>
  92.
  93.                         <page2_3_3>
  94.                             <label>Page 2.3.3</label>
  95.                             <uri>page2/page2_3/page2_3_3</uri>
  96.                             <resource>admin</resource>
  97.                             <pages>
  98.
  99.                                     <page2_3_3_1>
  100.                                         <label>Page 2.3.3.1</label>
  101.                                         <uri>page2/page2_3/page2_3_3/1</uri>
  102.                                         <active>1</active>
  103.                                     </page2_3_3_1>
  104.
  105.                                     <page2_3_3_2>
  106.                                         <label>Page 2.3.3.2</label>
  107.                                         <uri>page2/page2_3/page2_3_3/2</uri>
  108.                                         <resource>guest</resource>
  109.                                         <active>1</active>
  110.                                     </page2_3_3_2>
  111.
  112.                             </pages>
  113.                         </page2_3_3>
  114.
  115.                     </pages>
  116.                 </page2_3>
  117.
  118.             </pages>
  119.         </page2>
  120.
  121.         <page3>
  122.             <label>Page 3</label>
  123.             <uri>page3</uri>
  124.             <pages>
  125.
  126.                 <page3_1>
  127.                     <label>Page 3.1</label>
  128.                     <uri>page3/page3_1</uri>
  129.                     <resource>guest</resource>
  130.                 </page3_1>
  131.
  132.                 <page3_2>
  133.                     <label>Page 3.2</label>
  134.                     <uri>page3/page3_2</uri>
  135.                     <resource>member</resource>
  136.                     <pages>
  137.
  138.                         <page3_2_1>
  139.                             <label>Page 3.2.1</label>
  140.                             <uri>page3/page3_2/page3_2_1</uri>
  141.                         </page3_2_1>
  142.
  143.                         <page3_2_2>
  144.                             <label>Page 3.2.2</label>
  145.                             <uri>page3/page3_2/page3_2_2</uri>
  146.                             <resource>admin</resource>
  147.                         </page3_2_2>
  148.
  149.                     </pages>
  150.                 </page3_2>
  151.
  152.                 <page3_3>
  153.                     <label>Page 3.3</label>
  154.                     <uri>page3/page3_3</uri>
  155.                     <resource>special</resource>
  156.                     <pages>
  157.
  158.                         <page3_3_1>
  159.                             <label>Page 3.3.1</label>
  160.                             <uri>page3/page3_3/page3_3_1</uri>
  161.                             <visible>0</visible>
  162.                         </page3_3_1>
  163.
  164.                         <page3_3_2>
  165.                             <label>Page 3.3.2</label>
  166.                             <uri>page3/page3_3/page3_3_2</uri>
  167.                             <resource>admin</resource>
  168.                         </page3_3_2>
  169.
  170.                     </pages>
  171.                 </page3_3>
  172.
  173.             </pages>
  174.         </page3>
  175.
  176.         <home>
  177.             <label>Home</label>
  178.             <order>-100</order>
  179.             <module>default</module>
  180.             <controller>index</controller>
  181.             <action>index</action>
  182.         </home>
  183.
  184.     </nav>
  185. </config>
  186. */
  187.
  188. $config = new Zend_Config_Xml('/path/to/navigation.xml', 'nav');
  189. $container = new Zend_Navigation($config);

Adding pages

Adding pages to a container can be done with the methods addPage(), addPages(), or setPages(). See examples below for explanation.

Example #3 Adding pages to a container

  1. // create container
  2. $container = new Zend_Navigation();
  3.
  4. // add page by giving a page instance
  5. $container->addPage(Zend_Navigation_Page::factory(array(
  6.     'uri' => 'http://www.example.com/'
  7. )))
  8.
  9. // add page by giving an array
  10. $container->addPage(array(
  11.     'uri' => 'http://www.example.com/'
  12. )))
  13.
  14. // add page by giving a config object
  15. $container->addPage(new Zend_Config(array(
  16.     'uri' => 'http://www.example.com/'
  17. )))
  18.
  19. $pages = array(
  20.     array(
  21.         'label'  => 'Save'
  22.         'action' => 'save',
  23.     ),
  24.     array(
  25.         'label' =>  'Delete',
  26.         'action' => 'delete'
  27.     )
  28. );
  29.
  30. // add two pages
  31. $container->addPages($pages);
  32.
  33. // remove existing pages and add the given pages
  34. $container->setPages($pages);

Removing pages

Removing pages can be done with removePage() or removePages(). The first method accepts a an instance of a page, or an integer. The integer corresponds to the order a page has. The latter method will remove all pages in the container.

Example #4 Removing pages from a container

  1. $container = new Zend_Navigation(array(
  2.     array(
  3.         'label'  => 'Page 1',
  4.         'action' => 'page1'
  5.     ),
  6.     array(
  7.         'label'  => 'Page 2',
  8.         'action' => 'page2',
  9.         'order'  => 200
  10.     ),
  11.     array(
  12.         'label'  => 'Page 3',
  13.         'action' => 'page3'
  14.     )
  15. ));
  16.
  17. // remove page by implicit page order
  18. $container->removePage(0);      // removes Page 1
  19.
  20. // remove page by instance
  21. $page3 = $container->findOneByAction('Page 3');
  22. $container->removePage($page3); // removes Page 3
  23.
  24. // remove page by explicit page order
  25. $container->removePage(200);    // removes Page 2
  26.
  27. // remove all pages
  28. $container->removePages();      // removes all pages

Finding pages

Containers have finder methods for retrieving pages. They are findOneBy($property, $value), findAllBy($property, $value), and findBy($property, $value, $all = false). Those methods will recursively search the container for pages matching the given $page->$property == $value. The first method, findOneBy(), will return a single page matching the property with the given value, or NULL if it cannot be found. The second method will return all pages with a property matching the given value. The third method will call one of the two former methods depending on the $all flag.

The finder methods can also be used magically by appending the property name to findBy, findOneBy, or findAllBy, e.g. findOneByLabel('Home') to return the first matching page with label Home. Other combinations are findByLabel(...), findOnyByTitle(...), findAllByController(...), etc. Finder methods also work on custom properties, such as findByFoo('bar').

Example #5 Finding pages in a container

  1. $container = new Zend_Navigation(array(
  2.     array(
  3.         'label' => 'Page 1',
  4.         'uri'   => 'page-1',
  5.         'foo'   => 'bar',
  6.         'pages' => array(
  7.             array(
  8.                 'label' => 'Page 1.1',
  9.                 'uri'   => 'page-1.1',
  10.                 'foo'   => 'bar',
  11.             ),
  12.             array(
  13.                 'label' => 'Page 1.2',
  14.                 'uri'   => 'page-1.2',
  15.                 'class' => 'my-class',
  16.             ),
  17.             array(
  18.                 'type'   => 'uri',
  19.                 'label'  => 'Page 1.3',
  20.                 'uri'    => 'page-1.3',
  21.                 'action' => 'about'
  22.             )
  23.         )
  24.     ),
  25.     array(
  26.         'label'      => 'Page 2',
  27.         'id'         => 'page_2_and_3',
  28.         'class'      => 'my-class',
  29.         'module'     => 'page2',
  30.         'controller' => 'index',
  31.         'action'     => 'page1'
  32.     ),
  33.     array(
  34.         'label'      => 'Page 3',
  35.         'id'         => 'page_2_and_3',
  36.         'module'     => 'page3',
  37.         'controller' => 'index'
  38.     )
  39. ));
  40.
  41. // The 'id' is not required to be unique, but be aware that
  42. // having two pages with the same id will render the same id attribute
  43. // in menus and breadcrumbs.
  44. $found = $container->findBy('id',
  45.                             'page_2_and_3');      // returns Page 2
  46. $found = $container->findOneBy('id',
  47.                                'page_2_and_3');   // returns Page 2
  48. $found = $container->findBy('id',
  49.                             'page_2_and_3',
  50.                             true);                // returns Page 2 and Page 3
  51. $found = $container->findById('page_2_and_3');    // returns Page 2
  52. $found = $container->findOneById('page_2_and_3'); // returns Page 2
  53. $found = $container->findAllById('page_2_and_3'); // returns Page 2 and Page 3
  54.
  55. // Find all matching CSS class my-class
  56. $found = $container->findAllBy('class',
  57.                                'my-class');       // returns Page 1.2 and Page 2
  58. $found = $container->findAllByClass('my-class');  // returns Page 1.2 and Page 2
  59.
  60. // Find first matching CSS class my-class
  61. $found = $container->findOneByClass('my-class');  // returns Page 1.2
  62.
  63. // Find all matching CSS class non-existant
  64. $found = $container->findAllByClass('non-existant'); // returns array()
  65.
  66. // Find first matching CSS class non-existant
  67. $found = $container->findOneByClass('non-existant'); // returns null
  68.
  69. // Find all pages with custom property 'foo' = 'bar'
  70. $found = $container->findAllBy('foo', 'bar'); // returns Page 1 and Page 1.1
  71.
  72. // To achieve the same magically, 'foo' must be in lowercase.
  73. // This is because 'foo' is a custom property, and thus the
  74. // property name is not normalized to 'Foo'
  75. $found = $container->findAllByfoo('bar');
  76.
  77. // Find all with controller = 'index'
  78. $found = $container->findAllByController('index'); // returns Page 2 and Page 3

Iterating containers

Zend_Navigation_Container implements RecursiveIteratorIterator, and can be iterated using any Iterator class. To iterate a container recursively, use the RecursiveIteratorIterator class.

Example #6 Iterating a container

  1. /*
  2. * Create a container from an array
  3. */
  4. $container = new Zend_Navigation(array(
  5.     array(
  6.         'label' => 'Page 1',
  7.         'uri'   => '#'
  8.     ),
  9.     array(
  10.         'label' => 'Page 2',
  11.         'uri'   => '#',
  12.         'pages' => array(
  13.             array(
  14.                 'label' => 'Page 2.1',
  15.                 'uri'   => '#'
  16.             ),
  17.             array(
  18.                 'label' => 'Page 2.2',
  19.                 'uri'   => '#'
  20.             )
  21.         )
  22.     )
  23.     array(
  24.         'label' => 'Page 3',
  25.         'uri'   => '#'
  26.     )
  27. ));
  28.
  29. // Iterate flat using regular foreach:
  30. // Output: Page 1, Page 2, Page 3
  31. foreach ($container as $page) {
  32.     echo $page->label;
  33. }
  34.
  35. // Iterate recursively using RecursiveIteratorIterator
  36. $it = new RecursiveIteratorIterator(
  37.         $container, RecursiveIteratorIterator::SELF_FIRST);
  38.
  39. // Output: Page 1, Page 2, Page 2.1, Page 2.2, Page 3
  40. foreach ($it as $page) {
  41.     echo $page->label;
  42. }

Other operations

The method hasPage(Zend_Navigation_Page $page) checks if the container has the given page. The method hasPages() checks if there are any pages in the container, and is equivalent to count($container) > 1.

The toArray() method converts the container and the pages in it to an array. This can be useful for serializing and debugging.

Example #7 Converting a container to an array

  1. $container = new Zend_Navigation(array(
  2.     array(
  3.         'label' => 'Page 1',
  4.         'uri'   => '#'
  5.     ),
  6.     array(
  7.         'label' => 'Page 2',
  8.         'uri'   => '#',
  9.         'pages' => array(
  10.             array(
  11.                 'label' => 'Page 2.1',
  12.                 'uri'   => '#'
  13.             ),
  14.             array(
  15.                 'label' => 'Page 2.2',
  16.                'uri'   => '#'
  17.             )
  18.         )
  19.     )
  20. ));
  21.
  22. var_dump($container->toArray());
  23.
  24. /* Output:
  25. array(2) {
  26.   [0]=> array(15) {
  27.     ["label"]=> string(6) "Page 1"
  28.     ["id"]=> NULL
  29.     ["class"]=> NULL
  30.     ["title"]=> NULL
  31.     ["target"]=> NULL
  32.     ["rel"]=> array(0) {
  33.     }
  34.     ["rev"]=> array(0) {
  35.     }
  36.     ["order"]=> NULL
  37.     ["resource"]=> NULL
  38.     ["privilege"]=> NULL
  39.     ["active"]=> bool(false)
  40.     ["visible"]=> bool(true)
  41.     ["type"]=> string(23) "Zend_Navigation_Page_Uri"
  42.     ["pages"]=> array(0) {
  43.     }
  44.     ["uri"]=> string(1) "#"
  45.   }
  46.   [1]=> array(15) {
  47.     ["label"]=> string(6) "Page 2"
  48.     ["id"]=> NULL
  49.     ["class"]=> NULL
  50.     ["title"]=> NULL
  51.     ["target"]=> NULL
  52.     ["rel"]=> array(0) {
  53.     }
  54.     ["rev"]=> array(0) {
  55.     }
  56.     ["order"]=> NULL
  57.     ["resource"]=> NULL
  58.     ["privilege"]=> NULL
  59.     ["active"]=> bool(false)
  60.     ["visible"]=> bool(true)
  61.     ["type"]=> string(23) "Zend_Navigation_Page_Uri"
  62.     ["pages"]=> array(2) {
  63.       [0]=> array(15) {
  64.         ["label"]=> string(8) "Page 2.1"
  65.         ["id"]=> NULL
  66.         ["class"]=> NULL
  67.         ["title"]=> NULL
  68.         ["target"]=> NULL
  69.         ["rel"]=> array(0) {
  70.         }
  71.         ["rev"]=> array(0) {
  72.         }
  73.         ["order"]=> NULL
  74.         ["resource"]=> NULL
  75.         ["privilege"]=> NULL
  76.         ["active"]=> bool(false)
  77.         ["visible"]=> bool(true)
  78.         ["type"]=> string(23) "Zend_Navigation_Page_Uri"
  79.         ["pages"]=> array(0) {
  80.         }
  81.         ["uri"]=> string(1) "#"
  82.       }
  83.       [1]=>
  84.       array(15) {
  85.         ["label"]=> string(8) "Page 2.2"
  86.         ["id"]=> NULL
  87.         ["class"]=> NULL
  88.         ["title"]=> NULL
  89.         ["target"]=> NULL
  90.         ["rel"]=> array(0) {
  91.         }
  92.         ["rev"]=> array(0) {
  93.         }
  94.         ["order"]=> NULL
  95.         ["resource"]=> NULL
  96.         ["privilege"]=> NULL
  97.         ["active"]=> bool(false)
  98.         ["visible"]=> bool(true)
  99.         ["type"]=> string(23) "Zend_Navigation_Page_Uri"
  100.         ["pages"]=> array(0) {
  101.         }
  102.         ["uri"]=> string(1) "#"
  103.       }
  104.     }
  105.     ["uri"]=> string(1) "#"
  106.   }
  107. }
  108. */
Pages
Zend_Navigation
Zend Framework手册 中文版
Zend_Oauth
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Navigation
  • Introduction
  • Pages
  • Containers


Zend_Oauth - Zend Framework Manual

Containers
Zend Framework Reference
Zend Framework手册 中文版
Introduction to OAuth

Zend_Oauth

Table of Contents
  • Introduction to OAuth
Containers
Zend Framework Reference
Zend Framework手册 中文版
Introduction to OAuth
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


Introduction to OAuth - Zend Framework Manual

Zend_Oauth
Zend_Oauth
Zend Framework手册 中文版
Zend_OpenId

Introduction to OAuth

OAuth allows you to approve access by any application to your private data stored a website without being forced to disclose your username or password. If you think about it, the practice of handing over your username and password for sites like Yahoo Mail or Twitter has been endemic for quite a while. This has raised some serious concerns because there's nothing to prevent other applications from misusing this data. Yes, some services may appear trustworthy but that is never guaranteed. OAuth resolves this problem by eliminating the need for any username and password sharing, replacing it with a user controlled authorization process.

This authorization process is token based. If you authorize an application (and by application we can include any web based or desktop application) to access your data, it will be in receipt of an Access Token associated with your account. Using this Access Token, the application can access your private data without continually requiring your credentials. In all this authorization delegation style of protocol is simply a more secure solution to the problem of accessing private data via any web service API.

OAuth is not a completely new idea, rather it is a standardized protocol building on the existing properties of protocols such as Google AuthSub, Yahoo BBAuth, Flickr API, etc. These all to some extent operate on the basis of exchanging user credentials for an Access Token of some description. The power of a standardized specification like OAuth is that it only requires a single implementation as opposed to many disparate ones depending on the web service. This standardization has not occurred independently of the major players, and indeed many now support OAuth as an alternative and future replacement for their own solutions.

Zend Framework's Zend_Oauth currently implements a full OAuth Consumer conforming to the OAuth Core 1.0 Revision A Specification (24 June 2009) via the Zend_Oauth_Consumer class.

Protocol Workflow

Before implementing OAuth it makes sense to understand how the protocol operates. To do so we'll take the example of Twitter which currently implements OAuth based on the OAuth Core 1.0 Revision A Specification. This example looks at the protocol from the perspectives of the User (who will approve access), the Consumer (who is seeking access) and the Provider (who holds the User's private data). Access may be read-only or read and write.

By chance, our User has decided that they want to utilise a new service called TweetExpress which claims to be capable of reposting your blog posts to Twitter in a manner of seconds. TweetExpress is a registered application on Twitter meaning that it has access to a Consumer Key and a Consumer Secret (all OAuth applications must have these from the Provider they will be accessing) which identify its requests to Twitter and that ensure all requests can be signed using the Consumer Secret to verify their origin.

To use TweetExpress you are asked to register for a new account, and after your registration is confirmed you are informed that TweetExpress will seek to associate your Twitter account with the service.

In the meantime TweetExpress has been busy. Before gaining your approval from Twitter, it has sent a HTTP request to Twitter's service asking for a new unauthorized Request Token. This token is not User specific from Twitter's perspective, but TweetExpress may use it specifically for the current User and should associate it with their account and store it for future use. TweetExpress now redirects the User to Twitter so they can approve TweetExpress' access. The URL for this redirect will be signed using TweetExpress' Consumer Secret and it will contain the unauthorized Request Token as a parameter.

At this point the User may be asked to log into Twitter and will now be faced with a Twitter screen asking if they approve this request by TweetExpress to access Twitter's API on the User's behalf. Twitter will record the response which we'll assume was positive. Based on the User's approval, Twitter will record the current unauthorized Request Token as having been approved by the User (thus making it User specific) and will generate a new value in the form of a verification code. The User is now redirected back to a specific callback URL used by TweetExpress (this callback URL may be registered with Twitter or dynamically set using an oauth_callback parameter in requests). The redirect URL will contain the newly generated verification code.

TweetExpress' callback URL will trigger an examination of the response to determine whether the User has granted their approval to Twitter. Assuming so, it may now exchange it's unauthorized Request Token for a fully authorized Access Token by sending a request back to Twitter including the Request Token and the received verification code. Twitter should now send back a response containing this Access Token which must be used in all requests used to access Twitter's API on behalf of the User. Twitter will only do this once they have confirmed the attached Request Token has not already been used to retrieve another Access Token. At this point, TweetExpress may confirm the receipt of the approval to the User and delete the original Request Token which is no longer needed.

From this point forward, TweetExpress may use Twitter's API to post new tweets on the User's behalf simply by accessing the API endpoints with a request that has been digitally signed (via HMAC-SHA1) with a combination of TweetExpress' Consumer Secret and the Access Key being used.

Although Twitter do not currently expire Access Tokens, the User is free to deauthorize TweetExpress from their Twitter account settings. Once deauthorized, TweetExpress' access will be cut off and their Access Token rendered invalid.

Security Architecture

OAuth was designed specifically to operate over an insecure HTTP connection and so the use of HTTPS is not required though obviously it would be desireable if available. Should a HTTPS connection be feasible, OAuth offers a signature method implementation called PLAINTEXT which may be utilised. Over a typical unsecured HTTP connection, the use of PLAINTEXT must be avoided and an alternate scheme using. The OAuth specification defines two such signature methods: HMAC-SHA1 and RSA-SHA1. Both are fully supported by Zend_Oauth.

These signature methods are quite easy to understand. As you can imagine, a PLAINTEXT signature method does nothing that bears mentioning since it relies on HTTPS. If you were to use PLAINTEXT over HTTP, you are left with a significant problem: there's no way to be sure that the content of any OAuth enabled request (which would include the OAuth Access Token) was altered en route. This is because unsecured HTTP requests are always at risk of eavesdropping, Man In The Middle (MITM) attacks, or other risks whereby a request can be retooled so to speak to perform tasks on behalf of the attacker by masquerading as the origin application without being noticed by the service provider.

HMAC-SHA1 and RSA-SHA1 alleviate this risk by digitally signing all OAuth requests with the original application's registered Consumer Secret. Assuming only the Consumer and the Provider know what this secret is, a middle-man can alter requests all they wish - but they will not be able to validly sign them and unsigned or invalidly signed requests would be discarded by both parties. Digital signatures therefore offer a guarantee that validly signed requests do come from the expected party and have not been altered en route. This is the core of why OAuth can operate over an unsecure connection.

How these digital signatures operate depends on the method used, i.e. HMAC-SHA1, RSA-SHA1 or perhaps another method defined by the service provider. HMAC-SHA1 is a simple mechanism which generates a Message Authentication Code (MAC) using a cryptographic hash function (i.e. SHA1) in combination with a secret key known only to the message sender and receiver (i.e. the OAuth Consumer Secret and the authorized Access Key combined). This hashing mechanism is applied to the parameters and content of any OAuth requests which are concatenated into a "base signature string" as defined by the OAuth specification.

RSA-SHA1 operates on similar principles except that the shared secret is, as you would expect, each parties' RSA private key. Both sides would have the other's public key with which to verify digital signatures. This does pose a level of risk compared to HMAC-SHA1 since the RSA method does not use the Access Key as part of the shared secret. This means that if the RSA private key of any Consumer is compromised, then all Access Tokens assigned to that Consumer are also. RSA imposes an all or nothing scheme. In general, the majority of service providers offering OAuth authorization have therefore tended to use HMAC-SHA1 by default, and those who offer RSA-SHA1 may offer fallback support to HMAC-SHA1.

While digital signatures add to OAuth's security they are still vulnerable to other forms of attack, such as replay attacks which copy earlier requests which were intercepted and validly signed at that time. An attacker can now resend the exact same request to a Provider at will at any time and intercept its results. This poses a significant risk but it is quiet simple to defend against - add a unique string (i.e. a nonce) to all requests which changes per request (thus continually changing the signature string) but which can never be reused because Providers actively track used nonces within the a certain window defined by the timestamp also attached to a request. You might first suspect that once you stop tracking a particular nonce, the replay could work but this ignore the timestamp which can be used to determine a request's age at the time it was validly signed. One can assume that a week old request used in an attempted replay should be summarily discarded!

As a final point, this is not an exhaustive look at the security architecture in OAuth. For example, what if HTTP requests which contain both the Access Token and the Consumer Secret are eavesdropped? The system relies on at one in the clear transmission of each unless HTTPS is active, so the obvious conclusion is that where feasible HTTPS is to be preferred leaving unsecured HTTP in place only where it is not possible or affordable to do so.

Zend_Oauth
Zend_Oauth
Zend Framework手册 中文版
Zend_OpenId
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Oauth
  • Introduction to OAuth


Zend_OpenId - Zend Framework Manual

Introduction to OAuth
Zend Framework Reference
Zend Framework手册 中文版
Introduction

Zend_OpenId

Table of Contents
  • Introduction
  • Zend_OpenId_Consumer Basics
  • Zend_OpenId_Provider
Introduction to OAuth
Zend Framework Reference
Zend Framework手册 中文版
Introduction
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


Introduction - Zend Framework Manual

Zend_OpenId
Zend_OpenId
Zend Framework手册 中文版
Zend_OpenId_Consumer Basics

Introduction

Zend_OpenId is a Zend Framework component that provides a simple API for building OpenID-enabled sites and identity providers.

What is OpenID?

OpenID is a set of protocols for user-centric digital identities. These protocols allows users to create an identity online, using an identity provider. This identity can be used on any site that supports OpenID. Using OpenID-enabled sites, users do not need to remember traditional authentication tokens such as usernames and passwords for each site. All OpenID-enabled sites accept a single OpenID identity. This identity is typically a URL. It may be the URL of the user's personal page, blog or other resource that may provide additional information about them. That mean a user needs just one identifier for all sites he or she uses. services. OpenID is an open, decentralized, and free user-centric solution. Users may choose which OpenID provider to use, or even create their own personal identity server. No central authority is required to approve or register OpenID-enabled sites or identity providers.

For more information about OpenID visit the » OpenID official site.

How Does it Work?

The purpose of the Zend_OpenId component is to implement the OpenID authentication protocol as described in the following sequence diagram:

< class="inlinemediaobject">

  1. Authentication is initiated by the end user, who passes their OpenID identifier to the OpenID consumer through a User-Agent.

  2. The OpenID consumer performs normalization and discovery on the user-supplied identifier. Through this process, the consumer obtains the claimed identifier, the URL of the OpenID provider and an OpenID protocol version.

  3. The OpenID consumer establishes an optional association with the provider using Diffie-Hellman keys. As a result, both parties have a common "shared secret" that is used for signing and verification of the subsequent messages.

  4. The OpenID consumer redirects the User-Agent to the URL of the OpenID provider with an OpenID authentication request.

  5. The OpenID provider checks if the User-Agent is already authenticated and, if not, offers to do so.

  6. The end user enters the required password.

  7. The OpenID provider checks if it is allowed to pass the user identity to the given consumer, and asks the user if necessary.

  8. The user allows or disallows passing his identity.

  9. The OpenID Provider redirects the User-Agent back to the OpenID consumer with an "authentication approved" or "failed" request.

  10. The OpenID consumer verifies the information received from the provider by using the shared secret it got in step 3 or by sending an additional direct request to the OpenID provider.

Zend_OpenId Structure

Zend_OpenId consists of two sub-packages. The first one is Zend_OpenId_Consumer for developing OpenID-enabled sites, and the second is Zend_OpenId_Provider for developing OpenID servers. They are completely independent of each other and may be used separately.

The only common code used by these sub-packages are the OpenID Simple Registration Extension implemented by Zend_OpenId_Extension_Sreg class and a set of utility functions implemented by the Zend_OpenId class.

Note: Zend_OpenId takes advantage of the » GMP extension, where available. Consider enabling the GMP extension for enhanced performance when using Zend_OpenId.

Supported OpenID Standards

The Zend_OpenId component supports the following standards:

  • OpenID Authentication protocol version 1.1

  • OpenID Authentication protocol version 2.0 draft 11

  • OpenID Simple Registration Extension version 1.0

  • OpenID Simple Registration Extension version 1.1 draft 1

Zend_OpenId
Zend_OpenId
Zend Framework手册 中文版
Zend_OpenId_Consumer Basics
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_OpenId
  • Introduction
  • Zend_OpenId_Consumer Basics
  • Zend_OpenId_Provider


Zend_OpenId_Consumer Basics - Zend Framework Manual

Introduction
Zend_OpenId
Zend Framework手册 中文版
Zend_OpenId_Provider

Zend_OpenId_Consumer Basics

Zend_OpenId_Consumer can be used to implement OpenID authentication for web sites.

OpenID Authentication

From a web site developer's point of view, the OpenID authentication process consists of three steps:

  1. Show OpenID authentication form

  2. Accept OpenID identity and pass it to the OpenID provider

  3. Verify response from the OpenID provider

The OpenID authentication protocol actually requires more steps, but many of them are encapsulated inside Zend_OpenId_Consumer and are therefore transparent to the developer.

The end user initiates the OpenID authentication process by submitting his or her identification credentials with the appropriate form. The following example shows a simple form that accepts an OpenID identifier. Note that the example only demonstrates a login.

Example #1 The Simple OpenID Login form

  1. <html><body>
  2. <form method="post" action="example-1_2.php"><fieldset>
  3. <legend>OpenID Login</legend>
  4. <input type="text" name="openid_identifier">
  5. <input type="submit" name="openid_action" value="login">
  6. </fieldset></form></body></html>

This form passes the OpenID identity on submission to the following PHP script that performs the second step of authentication. The PHP script need only call the Zend_OpenId_Consumer::login() method in this step. The first argument of this method is an accepted OpenID identity, and the second is the URL of a script that handles the third and last step of authentication.

Example #2 The Authentication Request Handler

  1. $consumer = new Zend_OpenId_Consumer();
  2. if (!$consumer->login($_POST['openid_identifier'], 'example-1_3.php')) {
  3.     die("OpenID login failed.");
  4. }

The Zend_OpenId_Consumer::login() method performs discovery on a given identifier, and, if successful, obtains the address of the identity provider and its local identifier. It then creates an association to the given provider so that both the site and provider share a secret that is used to sign the subsequent messages. Finally, it passes an authentication request to the provider. This request redirects the end user's web browser to an OpenID server site, where the user can continue the authentication process.

An OpenID provider usually asks users for their password (if they weren't previously logged-in), whether the user trusts this site and what information may be returned to the site. These interactions are not visible to the OpenID consumer, so it can not obtain the user's password or other information that the user did not has not directed the OpenID provider to share with it.

On success, Zend_OpenId_Consumer::login() does not return, instead performing an HTTP redirection. However, if there is an error it may return FALSE. Errors may occur due to an invalid identity, unresponsive provider, communication error, etc.

The third step of authentication is initiated by the response from the OpenID provider, after it has authenticated the user's password. This response is passed indirectly, as an HTTP redirection using the end user's web browser. The consumer must now simply check that this response is valid.

Example #3 The Authentication Response Verifier

  1. $consumer = new Zend_OpenId_Consumer();
  2. if ($consumer->verify($_GET, $id)) {
  3.     echo "VALID " . htmlspecialchars($id);
  4. } else {
  5.     echo "INVALID " . htmlspecialchars($id);
  6. }

This check is performed using the Zend_OpenId_Consumer::verify method, which takes an array of the HTTP request's arguments and checks that this response is properly signed by the OpenID provider. It may assign the claimed OpenID identity that was entered by end user in the first step using a second, optional argument.

Combining all Steps in One Page

The following example combines all three steps in one script. It doesn't provide any new functionality. The advantage of using just one script is that the developer need not specify URL's for a script to handle the next step. By default, all steps use the same URL. However, the script now includes some dispatch code to execute the appropriate code for each step of authentication.

Example #4 The Complete OpenID Login Script

  1. <?php
  2. $status = "";
  3. if (isset($_POST['openid_action']) &&
  4.     $_POST['openid_action'] == "login" &&
  5.     !empty($_POST['openid_identifier'])) {
  6.
  7.     $consumer = new Zend_OpenId_Consumer();
  8.     if (!$consumer->login($_POST['openid_identifier'])) {
  9.         $status = "OpenID login failed.";
  10.     }
  11. } else if (isset($_GET['openid_mode'])) {
  12.     if ($_GET['openid_mode'] == "id_res") {
  13.         $consumer = new Zend_OpenId_Consumer();
  14.         if ($consumer->verify($_GET, $id)) {
  15.             $status = "VALID " . htmlspecialchars($id);
  16.         } else {
  17.             $status = "INVALID " . htmlspecialchars($id);
  18.         }
  19.     } else if ($_GET['openid_mode'] == "cancel") {
  20.         $status = "CANCELLED";
  21.     }
  22. }
  23. ?>
  24. <html><body>
  25. <?php echo "$status<br>" ?>
  26. <form method="post">
  27. <fieldset>
  28. <legend>OpenID Login</legend>
  29. <input type="text" name="openid_identifier" value=""/>
  30. <input type="submit" name="openid_action" value="login"/>
  31. </fieldset>
  32. </form>
  33. </body></html>

In addition, this code differentiates between cancelled and invalid authentication responses. The provider returns a cancelled response if the identity provider is not aware of the supplied identity, the user is not logged in, or the user doesn't trust the site. An invalid response indicates that the response is not conformant to the OpenID protocol or is incorrectly signed.

Consumer Realm

When an OpenID-enabled site passes authentication requests to a provider, it identifies itself with a realm URL. This URL may be considered a root of a trusted site. If the user trusts the realm URL, he or she should also trust matched and subsequent URLs.

By default, the realm URL is automatically set to the URL of the directory in which the login script resides. This default value is useful for most, but not all, cases. Sometimes an entire domain, and not a directory should be trusted. Or even a combination of several servers in one domain.

To override the default value, developers may pass the realm URL as a third argument to the Zend_OpenId_Consumer::login method. In the following example, a single interaction asks for trusted access to all php.net sites.

Example #5 Authentication Request for Specified Realm

  1. $consumer = new Zend_OpenId_Consumer();
  2. if (!$consumer->login($_POST['openid_identifier'],
  3.                       'example-3_3.php',
  4.                       'http://*.php.net/')) {
  5.     die("OpenID login failed.");
  6. }

This example implements only the second step of authentication; the first and third steps are similar to the examples above.

Immediate Check

In some cases, an application need only check if a user is already logged in to a trusted OpenID server without any interaction with the user. The Zend_OpenId_Consumer::check method does precisely that. It is executed with the same arguments as Zend_OpenId_Consumer::login, but it doesn't display any OpenID server pages to the user. From the users point of view this process is transparent, and it appears as though they never left the site. The third step succeeds if the user is already logged in and trusted by the site, otherwise it will fail.

Example #6 Immediate Check without Interaction

  1. $consumer = new Zend_OpenId_Consumer();
  2. if (!$consumer->check($_POST['openid_identifier'], 'example-4_3.php')) {
  3.     die("OpenID login failed.");
  4. }

This example implements only the second step of authentication; the first and third steps are similar to the examples above.

Zend_OpenId_Consumer_Storage

There are three steps in the OpenID authentication procedure, and each step is performed by a separate HTTP request. To store information between requests, Zend_OpenId_Consumer uses internal storage.

Developers do not necessarily have to be aware of this storage because by default Zend_OpenId_Consumer uses file-based storage under the temporary directory- similar to PHP sessions. However, this storage may be not suitable in all cases. Some developers may want to store information in a database, while others may need to use common storage suitable for server farms. Fortunately, developers may easily replace the default storage with their own. To specify a custom storage mechanism, one need only extend the Zend_OpenId_Consumer_Storage class and pass this subclass to the Zend_OpenId_Consumer constructor in the first argument.

The following example demonstrates a simple storage mechanism that uses Zend_Db as its backend and exposes three groups of functions. The first group contains functions for working with associations, while the second group caches discovery information, and the third group can be used to check whether a response is unique. This class can easily be used with existing or new databases; if the required tables don't exist, it will create them.

Example #7 Database Storage

  1. class DbStorage extends Zend_OpenId_Consumer_Storage
  2. {
  3.     private $_db;
  4.     private $_association_table;
  5.     private $_discovery_table;
  6.     private $_nonce_table;
  7.
  8.     // Pass in the Zend_Db_Adapter object and the names of the
  9.     // required tables
  10.     public function __construct($db,
  11.                                 $association_table = "association",
  12.                                 $discovery_table = "discovery",
  13.                                 $nonce_table = "nonce")
  14.     {
  15.         $this->_db = $db;
  16.         $this->_association_table = $association_table;
  17.         $this->_discovery_table = $discovery_table;
  18.         $this->_nonce_table = $nonce_table;
  19.         $tables = $this->_db->listTables();
  20.
  21.         // If the associations table doesn't exist, create it
  22.         if (!in_array($association_table, $tables)) {
  23.             $this->_db->getConnection()->exec(
  24.                 "create table $association_table (" .
  25.                 " url     varchar(256) not null primary key," .
  26.                 " handle  varchar(256) not null," .
  27.                 " macFunc char(16) not null," .
  28.                 " secret  varchar(256) not null," .
  29.                 " expires timestamp" .
  30.                 ")");
  31.         }
  32.
  33.         // If the discovery table doesn't exist, create it
  34.         if (!in_array($discovery_table, $tables)) {
  35.             $this->_db->getConnection()->exec(
  36.                 "create table $discovery_table (" .
  37.                 " id      varchar(256) not null primary key," .
  38.                 " realId  varchar(256) not null," .
  39.                 " server  varchar(256) not null," .
  40.                 " version float," .
  41.                 " expires timestamp" .
  42.                 ")");
  43.         }
  44.
  45.         // If the nonce table doesn't exist, create it
  46.         if (!in_array($nonce_table, $tables)) {
  47.             $this->_db->getConnection()->exec(
  48.                 "create table $nonce_table (" .
  49.                 " nonce   varchar(256) not null primary key," .
  50.                 " created timestamp default current_timestamp" .
  51.                 ")");
  52.         }
  53.     }
  54.
  55.     public function addAssociation($url,
  56.                                    $handle,
  57.                                    $macFunc,
  58.                                    $secret,
  59.                                    $expires)
  60.     {
  61.         $table = $this->_association_table;
  62.         $secret = base64_encode($secret);
  63.         $this->_db->insert($table, array(
  64.             'url'     => $url,
  65.             'handle'  => $handle,
  66.             'macFunc' => $macFunc,
  67.             'secret'  => $secret,
  68.             'expires' => $expires,
  69.         ));
  70.         return true;
  71.     }
  72.
  73.     public function getAssociation($url,
  74.                                    &$handle,
  75.                                    &$macFunc,
  76.                                    &$secret,
  77.                                    &$expires)
  78.     {
  79.         $table = $this->_association_table;
  80.         $this->_db->delete(
  81.             $table, $this->_db->quoteInto('expires < ?', time())
  82.         );
  83.         $select = $this-_db->select()
  84.                 ->from($table, array('handle', 'macFunc', 'secret', 'expires'))
  85.                 ->where('url = ?', $url);
  86.         $res = $this->_db->fetchRow($select);
  87.
  88.         if (is_array($res)) {
  89.             $handle  = $res['handle'];
  90.             $macFunc = $res['macFunc'];
  91.             $secret  = base64_decode($res['secret']);
  92.             $expires = $res['expires'];
  93.             return true;
  94.         }
  95.         return false;
  96.     }
  97.
  98.     public function getAssociationByHandle($handle,
  99.                                            &$url,
  100.                                            &$macFunc,
  101.                                            &$secret,
  102.                                            &$expires)
  103.     {
  104.         $table = $this->_association_table;
  105.         $this->_db->delete(
  106.             $table, $this->_db->quoteInto('expires < ', time())
  107.         );
  108.         $select = $this->_db->select()
  109.                 ->from($table, array('url', 'macFunc', 'secret', 'expires')
  110.                 ->where('handle = ?', $handle);
  111.         $res = $select->fetchRow($select);
  112.
  113.         if (is_array($res)) {
  114.             $url     = $res['url'];
  115.             $macFunc = $res['macFunc'];
  116.             $secret  = base64_decode($res['secret']);
  117.             $expires = $res['expires'];
  118.             return true;
  119.         }
  120.         return false;
  121.     }
  122.
  123.     public function delAssociation($url)
  124.     {
  125.         $table = $this->_association_table;
  126.         $this->_db->query("delete from $table where url = '$url'");
  127.         return true;
  128.     }
  129.
  130.     public function addDiscoveryInfo($id,
  131.                                      $realId,
  132.                                      $server,
  133.                                      $version,
  134.                                      $expires)
  135.     {
  136.         $table = $this->_discovery_table;
  137.         $this->_db->insert($table, array(
  138.             'id'      => $id,
  139.             'realId'  => $realId,
  140.             'server'  => $server,
  141.             'version' => $version,
  142.             'expires' => $expires,
  143.         ));
  144.
  145.         return true;
  146.     }
  147.
  148.     public function getDiscoveryInfo($id,
  149.                                      &$realId,
  150.                                      &$server,
  151.                                      &$version,
  152.                                      &$expires)
  153.     {
  154.         $table = $this->_discovery_table;
  155.         $this->_db->delete($table, $this->quoteInto('expires < ?', time()));
  156.         $select = $this->_db->select()
  157.                 ->from($table, array('realId', 'server', 'version', 'expires'))
  158.                 ->where('id = ?', $id);
  159.         $res = $this->_db->fetchRow($select);
  160.
  161.         if (is_array($res)) {
  162.             $realId  = $res['realId'];
  163.             $server  = $res['server'];
  164.             $version = $res['version'];
  165.             $expires = $res['expires'];
  166.             return true;
  167.         }
  168.         return false;
  169.     }
  170.
  171.     public function delDiscoveryInfo($id)
  172.     {
  173.         $table = $this->_discovery_table;
  174.         $this->_db->delete($table, $this->_db->quoteInto('id = ?', $id));
  175.         return true;
  176.     }
  177.
  178.     public function isUniqueNonce($nonce)
  179.     {
  180.         $table = $this->_nonce_table;
  181.         try {
  182.             $ret = $this->_db->insert($table, array(
  183.                 'nonce' => $nonce,
  184.             ));
  185.         } catch (Zend_Db_Statement_Exception $e) {
  186.             return false;
  187.         }
  188.         return true;
  189.     }
  190.
  191.     public function purgeNonces($date=null)
  192.     {
  193.     }
  194. }
  195.
  196. $db = Zend_Db::factory('Pdo_Sqlite',
  197.     array('dbname'=>'/tmp/openid_consumer.db'));
  198. $storage = new DbStorage($db);
  199. $consumer = new Zend_OpenId_Consumer($storage);

This example doesn't list the OpenID authentication code itself, but this code would be the same as that for other examples in this chapter. examples.

Simple Registration Extension

In addition to authentication, the OpenID standard can be used for lightweight profile exchange to make information about a user portable across multiple sites. This feature is not covered by the OpenID authentication specification, but by the OpenID Simple Registration Extension protocol. This protocol allows OpenID-enabled sites to ask for information about end users from OpenID providers. Such information may include:

  • nickname - any UTF-8 string that the end user uses as a nickname

  • email - the email address of the user as specified in section 3.4.1 of RFC2822

  • fullname - a UTF-8 string representation of the user's full name

  • dob - the user's date of birth in the format 'YYYY-MM-DD'. Any values whose representation uses fewer than the specified number of digits in this format should be zero-padded. In other words, the length of this value must always be 10. If the end user does not want to reveal any particular part of this value (i.e., year, month or day), it must be set to zero. For example, if the user wants to specify that his date of birth falls in 1980, but not specify the month or day, the value returned should be '1980-00-00'.

  • gender - the user's gender: "M" for male, "F" for female

  • postcode - a UTF-8 string that conforms to the postal system of the user's country

  • country - the user's country of residence as specified by ISO3166

  • language - the user's preferred language as specified by ISO639

  • timezone - an ASCII string from a TimeZone database. For example, "Europe/Paris" or "America/Los_Angeles".

An OpenID-enabled web site may ask for any combination of these fields. It may also strictly require some information and allow users to provide or hide additional information. The following example instantiates the Zend_OpenId_Extension_Sreg class, requiring a nickname and optionally requests an email and a fullname.

Example #8 Sending Requests with a Simple Registration Extension

  1. $sreg = new Zend_OpenId_Extension_Sreg(array(
  2.     'nickname'=>true,
  3.     'email'=>false,
  4.     'fullname'=>false), null, 1.1);
  5. $consumer = new Zend_OpenId_Consumer();
  6. if (!$consumer->login($_POST['openid_identifier'],
  7.                       'example-6_3.php',
  8.                       null,
  9.                       $sreg)) {
  10.     die("OpenID login failed.");
  11. }

As you can see, the Zend_OpenId_Extension_Sreg constructor accepts an array of OpenID fields. This array has the names of fields as indexes to a flag indicating whether the field is required; TRUE means the field is required and FALSE means the field is optional. The Zend_OpenId_Consumer::login method accepts an extension or an array of extensions as its fourth argument.

On the third step of authentication, the Zend_OpenId_Extension_Sreg object should be passed to Zend_OpenId_Consumer::verify. Then on successful authentication the Zend_OpenId_Extension_Sreg::getProperties method will return an associative array of requested fields.

Example #9 Verifying Responses with a Simple Registration Extension

  1. $sreg = new Zend_OpenId_Extension_Sreg(array(
  2.     'nickname'=>true,
  3.     'email'=>false,
  4.     'fullname'=>false), null, 1.1);
  5. $consumer = new Zend_OpenId_Consumer();
  6. if ($consumer->verify($_GET, $id, $sreg)) {
  7.     echo "VALID " . htmlspecialchars($id) ."<br>\n";
  8.     $data = $sreg->getProperties();
  9.     if (isset($data['nickname'])) {
  10.         echo "nickname: " . htmlspecialchars($data['nickname']) . "<br>\n";
  11.     }
  12.     if (isset($data['email'])) {
  13.         echo "email: " . htmlspecialchars($data['email']) . "<br>\n";
  14.     }
  15.     if (isset($data['fullname'])) {
  16.         echo "fullname: " . htmlspecialchars($data['fullname']) . "<br>\n";
  17.     }
  18. } else {
  19.     echo "INVALID " . htmlspecialchars($id);
  20. }

If the Zend_OpenId_Extension_Sreg object was created without any arguments, the user code should check for the existence of the required data itself. However, if the object is created with the same list of required fields as on the second step, it will automatically check for the existence of required data. In this case, Zend_OpenId_Consumer::verify will return FALSE if any of the required fields are missing.

Zend_OpenId_Extension_Sreg uses version 1.0 by default, because the specification for version 1.1 is not yet finalized. However, some libraries don't fully support version 1.0. For example, www.myopenid.com requires an SREG namespace in requests which is only available in 1.1. To work with such a server, you must explicitly set the version to 1.1 in the Zend_OpenId_Extension_Sreg constructor.

The second argument of the Zend_OpenId_Extension_Sreg constructor is a policy URL, that should be provided to the user by the identity provider.

Integration with Zend_Auth

Zend Framework provides a special class to support user authentication: Zend_Auth. This class can be used together with Zend_OpenId_Consumer. The following example shows how OpenIdAdapter implements the Zend_Auth_Adapter_Interface with the authenticate method. This performs an authentication query and verification.

The big difference between this adapter and existing ones, is that it works on two HTTP requests and includes a dispatch code to perform the second or third step of OpenID authentication.

Example #10 Zend_Auth Adapter for OpenID

  1. <?php
  2. class OpenIdAdapter implements Zend_Auth_Adapter_Interface {
  3.     private $_id = null;
  4.
  5.     public function __construct($id = null) {
  6.         $this->_id = $id;
  7.     }
  8.
  9.     public function authenticate() {
  10.         $id = $this->_id;
  11.         if (!empty($id)) {
  12.             $consumer = new Zend_OpenId_Consumer();
  13.             if (!$consumer->login($id)) {
  14.                 $ret = false;
  15.                 $msg = "Authentication failed.";
  16.             }
  17.         } else {
  18.             $consumer = new Zend_OpenId_Consumer();
  19.             if ($consumer->verify($_GET, $id)) {
  20.                 $ret = true;
  21.                 $msg = "Authentication successful";
  22.             } else {
  23.                 $ret = false;
  24.                 $msg = "Authentication failed";
  25.             }
  26.         }
  27.         return new Zend_Auth_Result($ret, $id, array($msg));
  28.     }
  29. }
  30.
  31. $status = "";
  32. $auth = Zend_Auth::getInstance();
  33. if ((isset($_POST['openid_action']) &&
  34.      $_POST['openid_action'] == "login" &&
  35.      !empty($_POST['openid_identifier'])) ||
  36.     isset($_GET['openid_mode'])) {
  37.     $adapter = new OpenIdAdapter(@$_POST['openid_identifier']);
  38.     $result = $auth->authenticate($adapter);
  39.     if ($result->isValid()) {
  40.         Zend_OpenId::redirect(Zend_OpenId::selfURL());
  41.     } else {
  42.         $auth->clearIdentity();
  43.         foreach ($result->getMessages() as $message) {
  44.             $status .= "$message<br>\n";
  45.         }
  46.     }
  47. } else if ($auth->hasIdentity()) {
  48.     if (isset($_POST['openid_action']) &&
  49.         $_POST['openid_action'] == "logout") {
  50.         $auth->clearIdentity();
  51.     } else {
  52.         $status = "You are logged in as " . $auth->getIdentity() . "<br>\n";
  53.     }
  54. }
  55. ?>
  56. <html><body>
  57. <?php echo htmlspecialchars($status);?>
  58. <form method="post"><fieldset>
  59. <legend>OpenID Login</legend>
  60. <input type="text" name="openid_identifier" value="">
  61. <input type="submit" name="openid_action" value="login">
  62. <input type="submit" name="openid_action" value="logout">
  63. </fieldset></form></body></html>

With Zend_Auth the end-user's identity is saved in the session's data. It may be checked with Zend_Auth::hasIdentity and Zend_Auth::getIdentity.

Integration with Zend_Controller

Finally a couple of words about integration into Model-View-Controller applications: such Zend Framework applications are implemented using the Zend_Controller class and they use objects of the Zend_Controller_Response_Http class to prepare HTTP responses and send them back to the user's web browser.

Zend_OpenId_Consumer doesn't provide any GUI capabilities but it performs HTTP redirections on success of Zend_OpenId_Consumer::login and Zend_OpenId_Consumer::check. These redirections may work incorrectly or not at all if some data was already sent to the web browser. To properly perform HTTP redirection in MVC code the real Zend_Controller_Response_Http should be sent to Zend_OpenId_Consumer::login or Zend_OpenId_Consumer::check as the last argument.

Introduction
Zend_OpenId
Zend Framework手册 中文版
Zend_OpenId_Provider
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_OpenId
  • Introduction
  • Zend_OpenId_Consumer Basics
  • Zend_OpenId_Provider


Zend_OpenId_Provider - Zend Framework Manual

Zend_OpenId_Consumer Basics
Zend_OpenId
Zend Framework手册 中文版
Zend_Paginator

Zend_OpenId_Provider

Zend_OpenId_Provider can be used to implement OpenID servers. This chapter provides examples that demonstrate how to build a very basic server. However, for implementation of a production OpenID server (such as » www.myopenid.com) you may have to deal with more complex issues.

Quick Start

The following example includes code for creating a user account using Zend_OpenId_Provider::register. The link element with rel="openid.server" points to our own server script. If you submit this identity to an OpenID-enabled site, it will perform authentication on this server.

The code before the <html> tag is just a trick that automatically creates a user account. You won't need such code when using real identities.

Example #1 The Identity

  1. <?php
  2. // Set up test identity
  3. define("TEST_SERVER", Zend_OpenId::absoluteURL("example-8.php"));
  4. define("TEST_ID", Zend_OpenId::selfURL());
  5. define("TEST_PASSWORD", "123");
  6. $server = new Zend_OpenId_Provider();
  7. if (!$server->hasUser(TEST_ID)) {
  8.     $server->register(TEST_ID, TEST_PASSWORD);
  9. }
  10. ?>
  11. <html><head>
  12. <link rel="openid.server" href="<?php echo TEST_SERVER;?>" />
  13. </head><body>
  14. <?php echo TEST_ID;?>
  15. </body></html>

The following identity server script handles two kinds of requests from OpenID-enabled sites (for association and authentication). Both of them are handled by the same method: Zend_OpenId_Provider::handle. The two arguments to the Zend_OpenId_Provider constructor are URLs of login and trust pages, which ask for input from the end user.

On success, the method Zend_OpenId_Provider::handle returns a string that should be passed back to the OpenID-enabled site. On failure, it returns FALSE. This example will return an HTTP 403 response if Zend_OpenId_Provider::handle fails. You will get this response if you open this script with a web browser, because it sends a non-OpenID conforming request.

Example #2 Simple Identity Provider

  1. $server = new Zend_OpenId_Provider("example-8-login.php",
  2.                                    "example-8-trust.php");
  3. $ret = $server->handle();
  4. if (is_string($ret)) {
  5.     echo $ret;
  6. } else if ($ret !== true) {
  7.     header('HTTP/1.0 403 Forbidden');
  8.     echo 'Forbidden';
  9. }

Note: It is a good idea to use a secure connection (HTTPS) for these scripts- especially for the following interactive scripts- to prevent password disclosure.

The following script implements a login screen for an identity server using Zend_OpenId_Provider and redirects to this page when a required user has not yet logged in. On this page, a user will enter his password to login.

You should use the password "123" that was used in the identity script above.

On submit, the script calls Zend_OpenId_Provider::login with the accepted user's identity and password, then redirects back to the main identity provider's script. On success, the Zend_OpenId_Provider::login establishes a session between the user and the identity provider and stores the information about the user, who is now logged in. All following requests from the same user won't require a login procedure- even if they come from another OpenID enabled web site.

Note: Note that this session is between end-user and identity provider only. OpenID enabled sites know nothing about it.

Example #3 Simple Login Screen

  1. <?php
  2. $server = new Zend_OpenId_Provider();
  3.
  4. if ($_SERVER['REQUEST_METHOD'] == 'POST' &&
  5.     isset($_POST['openid_action']) &&
  6.     $_POST['openid_action'] === 'login' &&
  7.     isset($_POST['openid_identifier']) &&
  8.     isset($_POST['openid_password'])) {
  9.     $server->login($_POST['openid_identifier'],
  10.                    $_POST['openid_password']);
  11.     Zend_OpenId::redirect("example-8.php", $_GET);
  12. }
  13. ?>
  14. <html>
  15. <body>
  16. <form method="post">
  17. <fieldset>
  18. <legend>OpenID Login</legend>
  19. <table border=0>
  20. <tr>
  21. <td>Name:</td>
  22. <td>
  23. <input type="text"
  24.        name="openid_identifier"
  25.        value="<?php echo htmlspecialchars($_GET['openid_identity']);?>">
  26. </td>
  27. </tr>
  28. <tr>
  29. <td>Password:</td>
  30. <td>
  31. <input type="text"
  32.        name="openid_password"
  33.        value="">
  34. </td>
  35. </tr>
  36. <tr>
  37. <td>&nbsp;</td>
  38. <td>
  39. <input type="submit"
  40.        name="openid_action"
  41.        value="login">
  42. </td>
  43. </tr>
  44. </table>
  45. </fieldset>
  46. </form>
  47. </body>
  48. </html>

The fact that the user is now logged in doesn't mean that the authentication must necessarily succeed. The user may decide not to trust particular OpenID enabled sites. The following trust screen allows the end user to make that choice. This choice may either be made only for current requests or forever. In the second case, information about trusted/untrusted sites is stored in an internal database, and all following authentication requests from this site will be handled automatically without user interaction.

Example #4 Simple Trust Screen

  1. <?php
  2. $server = new Zend_OpenId_Provider();
  3.
  4. if ($_SERVER['REQUEST_METHOD'] == 'POST' &&
  5.     isset($_POST['openid_action']) &&
  6.     $_POST['openid_action'] === 'trust') {
  7.
  8.     if (isset($_POST['allow'])) {
  9.         if (isset($_POST['forever'])) {
  10.             $server->allowSite($server->getSiteRoot($_GET));
  11.         }
  12.         $server->respondToConsumer($_GET);
  13.     } else if (isset($_POST['deny'])) {
  14.         if (isset($_POST['forever'])) {
  15.             $server->denySite($server->getSiteRoot($_GET));
  16.         }
  17.         Zend_OpenId::redirect($_GET['openid_return_to'],
  18.                               array('openid.mode'=>'cancel'));
  19.     }
  20. }
  21. ?>
  22. <html>
  23. <body>
  24. <p>A site identifying as
  25. <a href="<?php echo htmlspecialchars($server->getSiteRoot($_GET));?>">
  26. <?php echo htmlspecialchars($server->getSiteRoot($_GET));?>
  27. </a>
  28. has asked us for confirmation that
  29. <a href="<?php echo htmlspecialchars($server->getLoggedInUser());?>">
  30. <?php echo htmlspecialchars($server->getLoggedInUser());?>
  31. </a>
  32. is your identity URL.
  33. </p>
  34. <form method="post">
  35. <input type="checkbox" name="forever">
  36. <label for="forever">forever</label><br>
  37. <input type="hidden" name="openid_action" value="trust">
  38. <input type="submit" name="allow" value="Allow">
  39. <input type="submit" name="deny" value="Deny">
  40. </form>
  41. </body>
  42. </html>

Production OpenID servers usually support the Simple Registration Extension that allows consumers to request some information about the user from the provider. In this case, the trust page can be extended to allow entering requested fields or selecting a specific user profile.

Combined Provide Scripts

It is possible to combine all provider functionality in one script. In this case login and trust URLs are omitted, and Zend_OpenId_Provider assumes that they point to the same page with the additional "openid.action" GET argument.

Note: The following example is not complete. It doesn't provide GUI code for the user, instead performing an automatic login and trust relationship instead. This is done just to simplify the example; a production server should include some code from previous examples.

Example #5 Everything Together

  1. $server = new Zend_OpenId_Provider();
  2.
  3. define("TEST_ID", Zend_OpenId::absoluteURL("example-9-id.php"));
  4. define("TEST_PASSWORD", "123");
  5.
  6. if ($_SERVER['REQUEST_METHOD'] == 'GET' &&
  7.     isset($_GET['openid_action']) &&
  8.     $_GET['openid_action'] === 'login') {
  9.     $server->login(TEST_ID, TEST_PASSWORD);
  10.     unset($_GET['openid_action']);
  11.     Zend_OpenId::redirect(Zend_OpenId::selfUrl(), $_GET);
  12. } else if ($_SERVER['REQUEST_METHOD'] == 'GET' &&
  13.     isset($_GET['openid_action']) &&
  14.     $_GET['openid_action'] === 'trust') {
  15.     unset($_GET['openid_action']);
  16.     $server->respondToConsumer($_GET);
  17. } else {
  18.     $ret = $server->handle();
  19.     if (is_string($ret)) {
  20.         echo $ret;
  21.     } else if ($ret !== true) {
  22.         header('HTTP/1.0 403 Forbidden');
  23.         echo 'Forbidden';
  24.     }
  25. }

If you compare this example with previous examples split in to separate pages, you will see only the one difference besides the dispatch code: unset($_GET['openid_action']). This call to unset is necessary to route the next request to main handler.

Simple Registration Extension

Again, the code before the <html> tag is just a trick to demonstrate functionality. It creates a new user account and associates it with a profile (nickname and password). Such tricks aren't needed in deployed providers where end users register on OpenID servers and fill in their profiles. Implementing this GUI is out of scope for this manual.

Example #6 Identity with Profile

  1. <?php
  2. define("TEST_SERVER", Zend_OpenId::absoluteURL("example-10.php"));
  3. define("TEST_ID", Zend_OpenId::selfURL());
  4. define("TEST_PASSWORD", "123");
  5. $server = new Zend_OpenId_Provider();
  6. if (!$server->hasUser(TEST_ID)) {
  7.     $server->register(TEST_ID, TEST_PASSWORD);
  8.     $server->login(TEST_ID, TEST_PASSWORD);
  9.     $sreg = new Zend_OpenId_Extension_Sreg(array(
  10.         'nickname' =>'test',
  11.         'email' => 'test@test.com'
  12.     ));
  13.     $root = Zend_OpenId::absoluteURL(".");
  14.     Zend_OpenId::normalizeUrl($root);
  15.     $server->allowSite($root, $sreg);
  16.     $server->logout();
  17. }
  18. ?>
  19. <html>
  20. <head>
  21. <link rel="openid.server" href="<?php echo TEST_SERVER;?>" />
  22. </head>
  23. <body>
  24. <?php echo TEST_ID;?>
  25. </body>
  26. </html>

You should now pass this identity to the OpenID-enabled web site (use the Simple Registration Extension example from the previous section), and it should use the following OpenID server script.

This script is a variation of the script in the "Everything Together" example. It uses the same automatic login mechanism, but doesn't contain any code for a trust page. The user already trusts the example scripts forever. This trust was established by calling the Zend_OpenId_Provider::allowSite() method in the identity script. The same method associates the profile with the trusted URL. This profile will be returned automatically for a request from the trusted URL.

To make Simple Registration Extension work, you must simply pass an instance of Zend_OpenId_Extension_Sreg as the second argument to the Zend_OpenId_Provider::handle() method.

Example #7 Provider with SREG

  1. $server = new Zend_OpenId_Provider();
  2. $sreg = new Zend_OpenId_Extension_Sreg();
  3.
  4. define("TEST_ID", Zend_OpenId::absoluteURL("example-10-id.php"));
  5. define("TEST_PASSWORD", "123");
  6.
  7. if ($_SERVER['REQUEST_METHOD'] == 'GET' &&
  8.     isset($_GET['openid_action']) &&
  9.     $_GET['openid_action'] === 'login') {
  10.     $server->login(TEST_ID, TEST_PASSWORD);
  11.     unset($_GET['openid_action']);
  12.     Zend_OpenId::redirect(Zend_OpenId::selfUrl(), $_GET);
  13. } else if ($_SERVER['REQUEST_METHOD'] == 'GET' &&
  14.     isset($_GET['openid_action']) &&
  15.     $_GET['openid_action'] === 'trust') {
  16.    echo "UNTRUSTED DATA" ;
  17. } else {
  18.     $ret = $server->handle(null, $sreg);
  19.     if (is_string($ret)) {
  20.         echo $ret;
  21.     } else if ($ret !== true) {
  22.         header('HTTP/1.0 403 Forbidden');
  23.         echo 'Forbidden';
  24.     }
  25. }

Anything Else?

Building OpenID providers is much less common than building OpenID-enabled sites, so this manual doesn't cover all Zend_OpenId_Provider features exhaustively, as was done for Zend_OpenId_Consumer.

To summamize, Zend_OpenId_Provider contains:

  • A set of methods to build an end-user GUI that allows users to register and manage their trusted sites and profiles

  • An abstract storage layer to store information about users, their sites and their profiles. It also stores associations between the provider and OpenID-enabled sites. This layer is very similar to that of the Zend_OpenId_Consumer class. It also uses file storage by default, but may used with another backend.

  • An abstract user-association layer that may associate a user's web browser with a logged-in identity

The Zend_OpenId_Provider class doesn't attempt to cover all possible features that can be implemented by OpenID servers, e.g. digital certificates, but it can be extended easily using Zend_OpenId_Extensions or by standard object-oriented extension.

Zend_OpenId_Consumer Basics
Zend_OpenId
Zend Framework手册 中文版
Zend_Paginator
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_OpenId
  • Introduction
  • Zend_OpenId_Consumer Basics
  • Zend_OpenId_Provider


Zend_Paginator - Zend Framework Manual

Zend_OpenId_Provider
Zend Framework Reference
Zend Framework手册 中文版
Introduction

Zend_Paginator

Table of Contents
  • Introduction
  • Usage
  • Configuration
  • Advanced usage
Zend_OpenId_Provider
Zend Framework Reference
Zend Framework手册 中文版
Introduction
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


Introduction - Zend Framework Manual

Zend_Paginator
Zend_Paginator
Zend Framework手册 中文版
Usage

Introduction

Zend_Paginator is a flexible component for paginating collections of data and presenting that data to users.

The primary design goals of Zend_Paginator are as follows:

  • Paginate arbitrary data, not just relational databases

  • Fetch only the results that need to be displayed

  • Do not force users to adhere to only one way of displaying data or rendering pagination controls

  • Loosely couple Zend_Paginator to other Zend Framework components so that users who wish to use it independently of Zend_View, Zend_Db, etc. can do so

Zend_Paginator
Zend_Paginator
Zend Framework手册 中文版
Usage
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Paginator
  • Introduction
  • Usage
  • Configuration
  • Advanced usage


Usage - Zend Framework Manual

Introduction
Zend_Paginator
Zend Framework手册 中文版
Configuration

Usage

Paginating data collections

In order to paginate items into pages, Zend_Paginator must have a generic way of accessing that data. For that reason, all data access takes place through data source adapters. Several adapters ship with Zend Framework by default:

Adapters for Zend_Paginator
Adapter | Description
Array | Use a PHP array
DbSelect | Use a Zend_Db_Select instance, which will return an array
DbTableSelect | Use a Zend_Db_Table_Select instance, which will return an instance of Zend_Db_Table_Rowset_Abstract. This provides additional information about the result set, such as column names.
Iterator | Use an » Iterator instance
Null | Do not use Zend_Paginator to manage data pagination. You can still take advantage of the pagination control feature.

Note: Instead of selecting every matching row of a given query, the DbSelect and DbTableSelect adapters retrieve only the smallest amount of data necessary for displaying the current page.
Because of this, a second query is dynamically generated to determine the total number of matching rows. However, it is possible to directly supply a count or count query yourself. See the setRowCount() method in the DbSelect adapter for more information.

To create an instance of Zend_Paginator, you must supply an adapter to the constructor:

  1. $paginator = new Zend_Paginator(new Zend_Paginator_Adapter_Array($array));

For convenience, you may take advantage of the static factory() method for the adapters packaged with Zend Framework:

  1. $paginator = Zend_Paginator::factory($array);

Note: In the case of the Null adapter, in lieu of a data collection you must supply an item count to its constructor.

Although the instance is technically usable in this state, in your controller action you'll need to tell the paginator what page number the user requested. This allows him to advance through the paginated data.

  1. $paginator->setCurrentPageNumber($page);

The simplest way to keep track of this value is through a URL. Although we recommend using a Zend_Controller_Router_Interface-compatible router to handle this, it is not a requirement.

The following is an example route you might use in an INI configuration file:

  1. routes.example.route = articles/:articleName/:page
  2. routes.example.defaults.controller = articles
  3. routes.example.defaults.action = view
  4. routes.example.defaults.page = 1
  5. routes.example.reqs.articleName = \w+
  6. routes.example.reqs.page = \d+

With the above route (and using Zend Framework MVC components), you might set the current page number like this:

  1. $paginator->setCurrentPageNumber($this->_getParam('page'));

There are other options available; see Configuration for more on them.

Finally, you'll need to assign the paginator instance to your view. If you're using Zend_View with the ViewRenderer action helper, the following will work:

  1. $this->view->paginator = $paginator;

The DbSelect and DbTableSelect adapter

The usage of most adapters is pretty straight-forward. However, the database adapters require a more detailed explanation regarding the retrieval and count of the data from the database.

To use the DbSelect and DbTableSelect adapters you don't have to retrieve the data upfront from the database. Both adapters do the retrieval for you, aswell as the counting of the total pages. If additional work has to be done on the database results the adapter getItems() method has to be extended in your application.

Additionally these adapters do not fetch all records from the database in order to count them. Instead, the adapters manipulates the original query to produce the corresponding COUNT query. Paginator then executes that COUNT query to get the number of rows. This does require an extra round-trip to the database, but this is many times faster than fetching an entire result set and using count(). Especially with large collections of data.

The database adapters will try and build the most efficient query that will execute on pretty much all modern databases. However, depending on your database or even your own schema setup, there might be more efficient ways to get a rowcount. For this scenario the database adapters allow you to set a custom COUNT query. For example, if you keep track of the count of blog posts in a separate table, you could achieve a faster count query with the following setup:

  1. $adapter = new Zend_Paginator_Adapter_DbSelect($db->select()->from('posts'));
  2. $adapter->setRowCount(
  3.     $db->select()
  4.        ->from(
  5.             'item_counts',
  6.             array(
  7.                Zend_Paginator_Adapter_DbSelect::ROW_COUNT_COLUMN => 'post_count'
  8.             )
  9.          )
  10. );
  11.
  12. $paginator = new Zend_Paginator($adapter);

This approach will probably not give you a huge performance gain on small collections and/or simple select queries. However, with complex queries and large collections, a similar approach could give you a significant performance boost.

Rendering pages with view scripts

The view script is used to render the page items (if you're using Zend_Paginator to do so) and display the pagination control.

Because Zend_Paginator implements the SPL interface » IteratorAggregate, looping over your items and displaying them is simple.

  1. <html>
  2. <body>
  3. <h1>Example</h1>
  4. <?php if (count($this->paginator)): ?>
  5. <ul>
  6. <?php foreach ($this->paginator as $item): ?>
  7.   <li><?php echo $item; ?></li>
  8. <?php endforeach; ?>
  9. </ul>
  10. <?php endif; ?>
  11.
  12. <?php echo $this->paginationControl($this->paginator,
  13.                                     'Sliding',
  14.                                     'my_pagination_control.phtml'); ?>
  15. </body>
  16. </html>

Notice the view helper call near the end. PaginationControl accepts up to four parameters: the paginator instance, a scrolling style, a view partial, and an array of additional parameters.

The second and third parameters are very important. Whereas the view partial is used to determine how the pagination control should look, the scrolling style is used to control how it should behave. Say the view partial is in the style of a search pagination control, like the one below:

< class="inlinemediaobject">

What happens when the user clicks the "next" link a few times? Well, any number of things could happen. The current page number could stay in the middle as you click through (as it does on Yahoo!), or it could advance to the end of the page range and then appear again on the left when the user clicks "next" one more time. The page numbers might even expand and contract as the user advances (or "scrolls") through them (as they do on Google).

There are four scrolling styles packaged with Zend Framework:

Scrolling styles for Zend_Paginator
Scrolling style | Description
All | Returns every page. This is useful for dropdown menu pagination controls with relatively few pages. In these cases, you want all pages available to the user at once.
Elastic | A Google-like scrolling style that expands and contracts as a user scrolls through the pages.
Jumping | As users scroll through, the page number advances to the end of a given range, then starts again at the beginning of the new range.
Sliding | A Yahoo!-like scrolling style that positions the current page number in the center of the page range, or as close as possible. This is the default style.

The fourth and final parameter is reserved for an optional associative array of additional variables that you want available in your view partial (available via $this). For instance, these values could include extra URL parameters for pagination links.

By setting the default view partial, default scrolling style, and view instance, you can eliminate the calls to PaginationControl completely:

  1. Zend_Paginator::setDefaultScrollingStyle('Sliding');
  2. Zend_View_Helper_PaginationControl::setDefaultViewPartial(
  3.     'my_pagination_control.phtml'
  4. );
  5. $paginator->setView($view);

When all of these values are set, you can render the pagination control inside your view script with a simple echo statement:

  1. <?php echo $this->paginator; ?>

Note: Of course, it's possible to use Zend_Paginator with other template engines. For example, with Smarty you might do the following:

  1. $smarty->assign('pages', $paginator->getPages());
You could then access paginator values from a template like so:
  1. {$pages->pageCount}

Example pagination controls

The following example pagination controls will hopefully help you get started:

Search pagination:

  1. <!--
  2. See http://developer.yahoo.com/ypatterns/pattern.php?pattern=searchpagination
  3. -->
  4.
  5. <?php if ($this->pageCount): ?>
  6. <div class="paginationControl">
  7. <!-- Previous page link -->
  8. <?php if (isset($this->previous)): ?>
  9.   <a href="<?php echo $this->url(array('page' => $this->previous)); ?>">
  10.     &lt; Previous
  11.   </a> |
  12. <?php else: ?>
  13.   <span class="disabled">&lt; Previous</span> |
  14. <?php endif; ?>
  15.
  16. <!-- Numbered page links -->
  17. <?php foreach ($this->pagesInRange as $page): ?>
  18.   <?php if ($page != $this->current): ?>
  19.     <a href="<?php echo $this->url(array('page' => $page)); ?>">
  20.         <?php echo $page; ?>
  21.     </a> |
  22.   <?php else: ?>
  23.     <?php echo $page; ?> |
  24.   <?php endif; ?>
  25. <?php endforeach; ?>
  26.
  27. <!-- Next page link -->
  28. <?php if (isset($this->next)): ?>
  29.   <a href="<?php echo $this->url(array('page' => $this->next)); ?>">
  30.     Next &gt;
  31.   </a>
  32. <?php else: ?>
  33.   <span class="disabled">Next &gt;</span>
  34. <?php endif; ?>
  35. </div>
  36. <?php endif; ?>

Item pagination:

  1. <!--
  2. See http://developer.yahoo.com/ypatterns/pattern.php?pattern=itempagination
  3. -->
  4.
  5. <?php if ($this->pageCount): ?>
  6. <div class="paginationControl">
  7. <?php echo $this->firstItemNumber; ?> - <?php echo $this->lastItemNumber; ?>
  8. of <?php echo $this->totalItemCount; ?>
  9.
  10. <!-- First page link -->
  11. <?php if (isset($this->previous)): ?>
  12.   <a href="<?php echo $this->url(array('page' => $this->first)); ?>">
  13.     First
  14.   </a> |
  15. <?php else: ?>
  16.   <span class="disabled">First</span> |
  17. <?php endif; ?>
  18.
  19. <!-- Previous page link -->
  20. <?php if (isset($this->previous)): ?>
  21.   <a href="<?php echo $this->url(array('page' => $this->previous)); ?>">
  22.     &lt; Previous
  23.   </a> |
  24. <?php else: ?>
  25.   <span class="disabled">&lt; Previous</span> |
  26. <?php endif; ?>
  27.
  28. <!-- Next page link -->
  29. <?php if (isset($this->next)): ?>
  30.   <a href="<?php echo $this->url(array('page' => $this->next)); ?>">
  31.     Next &gt;
  32.   </a> |
  33. <?php else: ?>
  34.   <span class="disabled">Next &gt;</span> |
  35. <?php endif; ?>
  36.
  37. <!-- Last page link -->
  38. <?php if (isset($this->next)): ?>
  39.   <a href="<?php echo $this->url(array('page' => $this->last)); ?>">
  40.     Last
  41.   </a>
  42. <?php else: ?>
  43.   <span class="disabled">Last</span>
  44. <?php endif; ?>
  45.
  46. </div>
  47. <?php endif; ?>

Dropdown pagination:

  1. <?php if ($this->pageCount): ?>
  2. <select id="paginationControl" size="1">
  3. <?php foreach ($this->pagesInRange as $page): ?>
  4.   <?php $selected = ($page == $this->current) ? ' selected="selected"' : ''; ?>
  5.   <option value="<?php
  6.         echo $this->url(array('page' => $page));?>"<?php echo $selected ?>>
  7.     <?php echo $page; ?>
  8.   </option>
  9. <?php endforeach; ?>
  10. </select>
  11. <?php endif; ?>
  12.
  13. <script type="text/javascript"
  14.      src="http://ajax.googleapis.com/ajax/libs/prototype/1.6.0.2/prototype.js">
  15. </script>
  16. <script type="text/javascript">
  17. $('paginationControl').observe('change', function() {
  18.     window.location = this.options[this.selectedIndex].value;
  19. })
  20. </script>

Listing of properties

The following options are available to pagination control view partials:

Properties available to view partials
Property | Type | Description
first | integer | First page number (i.e., 1)
firstItemNumber | integer | Absolute number of the first item on this page
firstPageInRange | integer | First page in the range returned by the scrolling style
current | integer | Current page number
currentItemCount | integer | Number of items on this page
itemCountPerPage | integer | Maximum number of items available to each page
last | integer | Last page number
lastItemNumber | integer | Absolute number of the last item on this page
lastPageInRange | integer | Last page in the range returned by the scrolling style
next | integer | Next page number
pageCount | integer | Number of pages
pagesInRange | array | Array of pages returned by the scrolling style
previous | integer | Previous page number
totalItemCount | integer | Total number of items
Introduction
Zend_Paginator
Zend Framework手册 中文版
Configuration
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Paginator
  • Introduction
  • Usage
  • Configuration
  • Advanced usage


Configuration - Zend Framework Manual

Usage
Zend_Paginator
Zend Framework手册 中文版
Advanced usage

Configuration

Zend_Paginator has several configuration methods that can be called:

Configuration methods for Zend_Paginator
Method | Description
setCurrentPageNumber | Sets the current page number (default 1).
setItemCountPerPage | Sets the maximum number of items to display on a page (default 10).
setPageRange | Sets the number of items to display in the pagination control (default 10). Note: Most of the time this number will be adhered to exactly, but scrolling styles do have the option of only using it as a guideline or starting value (e.g., Elastic).
setView | Sets the view instance, for rendering convenience.
Usage
Zend_Paginator
Zend Framework手册 中文版
Advanced usage
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Paginator
  • Introduction
  • Usage
  • Configuration
  • Advanced usage


Advanced usage - Zend Framework Manual

Configuration
Zend_Paginator
Zend Framework手册 中文版
Zend_Pdf

Advanced usage

Custom data source adapters

At some point you may run across a data type that is not covered by the packaged adapters. In this case, you will need to write your own.

To do so, you must implement Zend_Paginator_Adapter_Interface. There are two methods required to do this:

  • count()

  • getItems($offset, $itemCountPerPage)

Additionally, you'll want to implement a constructor that takes your data source as a parameter and stores it as a protected or private property. How you wish to go about doing this specifically is up to you.

If you've ever used the SPL interface » Countable, you're familiar with count(). As used with Zend_Paginator, this is the total number of items in the data collection. Additionally, the Zend_Paginator instance provides a method countAllItems() that proxies to the adapter count() method.

The getItems() method is only slightly more complicated. For this, your adapter is supplied with an offset and the number of items to display per page. You must return the appropriate slice of data. For an array, that would be:

  1. return array_slice($this->_array, $offset, $itemCountPerPage);

Take a look at the packaged adapters (all of which implement the Zend_Paginator_Adapter_Interface) for ideas of how you might go about implementing your own.

Custom scrolling styles

Creating your own scrolling style requires that you implement Zend_Paginator_ScrollingStyle_Interface, which defines a single method, getPages(). Specifically,

  1. public function getPages(Zend_Paginator $paginator, $pageRange = null);

This method should calculate a lower and upper bound for page numbers within the range of so-called "local" pages (that is, pages that are nearby the current page).

Unless it extends another scrolling style (see Zend_Paginator_ScrollingStyle_Elastic for an example), your custom scrolling style will inevitably end with something similar to the following line of code:

  1. return $paginator->getPagesInRange($lowerBound, $upperBound);

There's nothing special about this call; it's merely a convenience method to check the validity of the lower and upper bound and return an array of the range to the paginator.

When you're ready to use your new scrolling style, you'll need to tell Zend_Paginator what directory to look in. To do that, do the following:

  1. $prefix = 'My_Paginator_ScrollingStyle';
  2. $path   = 'My/Paginator/ScrollingStyle/';
  3. Zend_Paginator::addScrollingStylePrefixPath($prefix, $path);

Caching features

Zend_Paginator can be told to cache the data it has already passed on, preventing the adapter from fetching them each time they are used. To tell paginator to automatically cache the adapter's data, just pass to its setCache() method a Zend_Cache_Core instance.

  1. $paginator = Zend_Paginator::factory($someData);
  2. $fO = array('lifetime' => 3600, 'automatic_serialization' => true);
  3. $bO = array('cache_dir'=>'/tmp');
  4. $cache = Zend_cache::factory('Core', 'File', $fO, $bO);
  5. Zend_Paginator::setCache($cache);

As far as Zend_Paginator has got a Zend_Cache_Core instance, data will be cached. Sometimes you would like not to cache data even if you already passed a cache instance. You should then use setCacheEnable() for that.

  1. $paginator = Zend_Paginator::factory($someData);
  2. // $cache is a Zend_Cache_Core instance
  3. Zend_Paginator::setCache($cache);
  4. // ... later on the script
  5. $paginator->setCacheEnable(false);
  6. // cache is now disabled

When a cache is set, data are automatically stored in it and pulled out from it. It then can be useful to empty the cache manually. You can get this done by calling clearPageItemCache($pageNumber). If you don't pass any parameter, the whole cache will be empty. You can optionally pass a parameter representing the page number to empty in the cache:

  1. $paginator = Zend_Paginator::factory($someData);
  2. Zend_Paginator::setCache($cache);
  3. $items = $paginator->getCurrentItems();
  4. // page 1 is now in cache
  5. $page3Items = $paginator->getItemsByPage(3);
  6. // page 3 is now in cache
  7.
  8. // clear the cache of the results for page 3
  9. $paginator->clearPageItemCache(3);
  10.
  11. // clear all the cache data
  12. $paginator->clearPageItemCache();

Changing the item count per page will empty the whole cache as it would have become invalid:

  1. $paginator = Zend_Paginator::factory($someData);
  2. Zend_Paginator::setCache($cache);
  3. // fetch some items
  4. $items = $paginator->getCurrentItems();
  5.
  6. // all the cache data will be flushed:
  7. $paginator->setItemCountPerPage(2);

It is also possible to see the data in cache and ask for them directly. getPageItemCache() can be used for that:

  1. $paginator = Zend_Paginator::factory($someData);
  2. $paginator->setItemCountPerPage(3);
  3. Zend_Paginator::setCache($cache);
  4.
  5. // fetch some items
  6. $items = $paginator->getCurrentItems();
  7. $otherItems = $paginator->getItemsPerPage(4);
  8.
  9. // see the cached items as a two-dimension array:
  10. var_dump($paginator->getPageItemCache());

Zend_Paginator_AdapterAggregate Interface

Depending on your application you might want to paginate objects, whose internal data-structure is equal to existing adapters, but you don't want to break up your encapsulation to allow access to this data. In other cases an object might be in a "has-an adapter" relationship, rather than the "is-an adapter" relationsship that Zend_Paginator_Adapter_Abstract promotes. For this cases you can use the Zend_Paginator_AdapterAggregate interface that behaves much like the IteratorAggregate interface of the PHP SPL extension.

  1. interface Zend_Paginator_AdapterAggregate
  2. {
  3.     /**
  4.      * Return a fully configured Paginator Adapter from this method.
  5.      *
  6.      * @return Zend_Paginator_Adapter_Abstract
  7.      */
  8.     public function getPaginatorAdapter();
  9. }

The interface is fairly small and only expects you to return an instance of Zend_Paginator_Adapter_Abstract. An Adapter Aggregate instance is then recognized by both Zend_Paginator::factory and the constructor of Zend_Paginator and handled accordingly.

Configuration
Zend_Paginator
Zend Framework手册 中文版
Zend_Pdf
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Paginator
  • Introduction
  • Usage
  • Configuration
  • Advanced usage


Zend_Pdf - Zend Framework Manual

Advanced usage
Zend Framework Reference
Zend Framework手册 中文版
简介

Zend_Pdf

Table of Contents
  • 简介
  • 生成和加载 PDF 文档
  • 保存修改到 PDF 文档
  • 文档页面
  • Drawing
  • Interactive Features
  • Document Info and Metadata
  • Zend_Pdf module usage example
Advanced usage
Zend Framework Reference
Zend Framework手册 中文版
简介
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


简介 - Zend Framework Manual

Zend_Pdf
Zend_Pdf
Zend Framework手册 中文版
生成和加载 PDF 文档

简介

Zend_Pdf module 是个完全用 PHP 5 编写的 PDF (Portable Document Format) 处理引擎。它可加载存在的文档，生成新的、修改和保存修改后的文档。这样，它可帮助任何 PHP 程序通过修改存在的模板或生成新的文档来动态地准备 PDF 格式的文档。 Zend_Pdf 模块支持下列功能：

  • 生成新文档或加载已存在的文档。 [1]

  • 读取指定版本的文档。

  • 在文档中处理页面。修改页顺序、添加新的页和删除页。

  • 生成不同的图案（线、矩形、多边形、圆、椭圆和扇形）。

  • 使用任何 14 标准（内置）字体或自己定制的 TrueType 字体来生成文本（Text drawing）。

  • 旋转。

  • 生成图像。 [2]

  • 增量式 PDF 文件更新。

[1] 现在支持 PDF V1.4 (Acrobat 5) 文档。
[2] 支持 JPG、 PNG [最多 8bit per channel+Alpha] 和 TIFF 图像。
Zend_Pdf
Zend_Pdf
Zend Framework手册 中文版
生成和加载 PDF 文档
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Pdf
  • 简介
  • 生成和加载 PDF 文档
  • 保存修改到 PDF 文档
  • 文档页面
  • Drawing
  • Interactive Features
  • Document Info and Metadata
  • Zend_Pdf module usage example


生成和加载 PDF 文档 - Zend Framework Manual

简介
Zend_Pdf
Zend Framework手册 中文版
保存修改到 PDF 文档

生成和加载 PDF 文档

Zend_Pdf 类描绘 PDF 文档自己和提供文档一级的功能。

要生成新文档，需要创建 Zend_Pdf 对象。

Zend_Pdf 类也提供两个静态方法来加载 PDF，Zend_Pdf::load() 和 Zend_Pdf::parse()。它们都返回 Zend_Pdf 对象作为结果或如果有错误发生就抛出异常。

Example #1 生成新的或加载 PDF 文档

...
// Create new PDF document.
$pdf1 = new Zend_Pdf();

// Load PDF document from a file.
$pdf2 = Zend_Pdf::load($fileName);

// Load PDF document from a string.
$pdf3 = Zend_Pdf::parse($pdfString);
...

PDF 文件格式支持增量式文档更新。这样每次文档更新，就产生新的版本。Zend_Pdf 模块支持指定版本的读取。

   版本可以指定为 Zend_Pdf::load() 和 Zend_Pdf::parse()的第二个参数或由 Zend_Pdf::rollback() 来请求。
    [1]

            Zend_Pdf::rollback()

call.

Example #2 请求 PDF 文档的指定版本

...
// Load PDF previouse revision of the document.
$pdf1 = Zend_Pdf::load($fileName, 1);

// Load PDF previouse revision of the document.
$pdf2 = Zend_Pdf::parse($pdfString, 1);

// Load first revision of the document.
$pdf3 = Zend_Pdf::load($fileName);
$revisions = $pdf3->revisions();
$pdf3->rollback($revisions - 1);
...
[1] 方法必需在任何修改前调用，否则它的行为就没有定义。
简介
Zend_Pdf
Zend Framework手册 中文版
保存修改到 PDF 文档
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Pdf
  • 简介
  • 生成和加载 PDF 文档
  • 保存修改到 PDF 文档
  • 文档页面
  • Drawing
  • Interactive Features
  • Document Info and Metadata
  • Zend_Pdf module usage example


保存修改到 PDF 文档 - Zend Framework Manual

生成和加载 PDF 文档
Zend_Pdf
Zend Framework手册 中文版
文档页面

保存修改到 PDF 文档

有两个方法来保存修改到 PDF 文档：Zend_Pdf::save() 和 Zend_Pdf::render()。

Zend_Pdf::save($filename, $updateOnly = false) 保存 PDF 文档到一个文件。如果 $updateOnly 是 true，那么只有新的 PDF 文件段被追加到文件，否则，重写文件。

Zend_Pdf::render($newSegmentOnly = false) 把 PDF 文档当作字符串返回。如果 $newSegmentOnly 是 true，那么只有新的 PDF 文件段返回。

Example #1 Save PDF document.

...
// Load PDF document.
$pdf = Zend_Pdf::load($fileName);
...
// Update document
$pdf->save($fileName, true);
// Save document as a new file
$pdf->save($newFileName);

// Return PDF document as a string.
$pdfString = $pdf->render();

...
生成和加载 PDF 文档
Zend_Pdf
Zend Framework手册 中文版
文档页面
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Pdf
  • 简介
  • 生成和加载 PDF 文档
  • 保存修改到 PDF 文档
  • 文档页面
  • Drawing
  • Interactive Features
  • Document Info and Metadata
  • Zend_Pdf module usage example


文档页面 - Zend Framework Manual

保存修改到 PDF 文档
Zend_Pdf
Zend Framework手册 中文版
Drawing

文档页面

页面生成

PDF 文档页面摘要由 Zend_Pdf_Page 类来描绘。

PDF 页面或者从 PDF 加载，或者生成新的。

新页面可以通过创建 Zend_Pdf_Page 对象或调用 Zend_Pdf::newPage() 方法来获得，它返回 Zend_Pdf_Page 对象。Zend_Pdf::newPage() 方法生成已经附加到文档的页面，和未附加的页面不同的是它不能和若干个 PDF 文档一起用，但是性能会稍好一些。 [1] . 选择那种方式是你的自由。

Zend_Pdf::newPage() 方法和 Zend_Pdf_Page 构造器带有相同的指定页面尺寸的参数。它或者是以点（1/72 英寸）来计算的页面的尺寸（$x,$y），或者以预先定义的常数来计算，常数就是页面类型：

  • Zend_Pdf_Page::SIZE_A4

  • Zend_Pdf_Page::SIZE_A4_LANDSCAPE

  • Zend_Pdf_Page::SIZE_LETTER

  • Zend_Pdf_Page::SIZE_LETTER_LANDSCAPE

文档存储在 Zend_Pdf 类的 public 成员 $pages 里，它是 Zend_Pdf_Page 对象的一个数组。它完整地定义了设置和文档页面的顺序并可以以普通的数组来处理：

Example #1 PDF 文档页面管理

<?php
    ...
    // Reverse page order
    $pdf->pages = array_reverse($pdf->pages);
    ...
    // Add new page
    $pdf->pages[] = new Zend_Pdf_Page(Zend_Pdf_Page::SIZE_A4);
    // Add new page
    $pdf->pages[] = $pdf->newPage(Zend_Pdf_Page::SIZE_A4);

    // Remove specified page.
    unset($pdf->pages[$id]);

    ...

页面克隆

通过用页面为参数创建 Zend_Pdf_Page 对象 PDF 页面可以被克隆：

Example #2 Cloning existing page.

<?php
    ...
    // Store template page in a separate variable
    $template = $pdf->pages[$templatePageIndex];
    ...
    // Add new page
    $page1 = new Zend_Pdf_Page($template);
    $pdf->pages[] = $page1;
    ...

    // Add another page
    $page2 = new Zend_Pdf_Page($template);
    $pdf->pages[] = $page2;
    ...

    // Remove source template page from the documents.
    unset($pdf->pages[$templatePageIndex]);

    ...

如果你需要用同一个模板生成若干页面，这很有用。

Caution

重要！克隆页面用模板页面来共享一些 PDF 资源，它只可以用于使用模板页的同一个文档内。修改后的文档可当作新文件来保存。

[1] Zend_Pdf 模块的 V1.0 有点限制，会在将来的版本中改善。但未附加的页面总是为在文档间共享提供更好（更多的优化）的结果。
保存修改到 PDF 文档
Zend_Pdf
Zend Framework手册 中文版
Drawing
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Pdf
  • 简介
  • 生成和加载 PDF 文档
  • 保存修改到 PDF 文档
  • 文档页面
  • Drawing
  • Interactive Features
  • Document Info and Metadata
  • Zend_Pdf module usage example


Drawing - Zend Framework Manual

文档页面
Zend_Pdf
Zend Framework手册 中文版
Interactive Features

Drawing

Geometry

PDF uses the same geometry as PostScript. It starts from bottom-left corner of page and by default is measured in points (1/72 of an inch).

Page size can be retrieved from a page object:

  1. $width  = $pdfPage->getWidth();
  2. $height = $pdfPage->getHeight();

Colors

PDF has a powerful capabilities for colors representation. Zend_Pdf module supports Gray Scale, RGB and CMYK color spaces. Any of them can be used in any place, where Zend_Pdf_Color object is required. Zend_Pdf_Color_GrayScale, Zend_Pdf_Color_Rgb and Zend_Pdf_Color_Cmyk classes provide this functionality:

  1. // $grayLevel (float number). 0.0 (black) - 1.0 (white)
  2. $color1 = new Zend_Pdf_Color_GrayScale($grayLevel);
  3.
  4. // $r, $g, $b (float numbers). 0.0 (min intensity) - 1.0 (max intensity)
  5. $color2 = new Zend_Pdf_Color_Rgb($r, $g, $b);
  6.
  7. // $c, $m, $y, $k (float numbers). 0.0 (min intensity) - 1.0 (max intensity)
  8. $color3 = new Zend_Pdf_Color_Cmyk($c, $m, $y, $k);

HTML style colors are also provided with Zend_Pdf_Color_Html class:

  1. $color1 = new Zend_Pdf_Color_Html('#3366FF');
  2. $color2 = new Zend_Pdf_Color_Html('silver');
  3. $color3 = new Zend_Pdf_Color_Html('forestgreen');

Shape Drawing

All drawing operations can be done in a context of PDF page.

Zend_Pdf_Page class provides a set of drawing primitives:

  1. /**
  2. * Draw a line from x1,y1 to x2,y2.
  3. *
  4. * @param float $x1
  5. * @param float $y1
  6. * @param float $x2
  7. * @param float $y2
  8. * @return Zend_Pdf_Page
  9. */
  10. public function drawLine($x1, $y1, $x2, $y2);
  1. /**
  2. * Draw a rectangle.
  3. *
  4. * Fill types:
  5. * Zend_Pdf_Page::SHAPE_DRAW_FILL_AND_STROKE - fill rectangle
  6. *                                             and stroke (default)
  7. * Zend_Pdf_Page::SHAPE_DRAW_STROKE          - stroke rectangle
  8. * Zend_Pdf_Page::SHAPE_DRAW_FILL            - fill rectangle
  9. *
  10. * @param float $x1
  11. * @param float $y1
  12. * @param float $x2
  13. * @param float $y2
  14. * @param integer $fillType
  15. * @return Zend_Pdf_Page
  16. */
  17. public function drawRectangle($x1, $y1, $x2, $y2,
  18.                     $fillType = Zend_Pdf_Page::SHAPE_DRAW_FILL_AND_STROKE);
  1. /**
  2. * Draw a rounded rectangle.
  3. *
  4. * Fill types:
  5. * Zend_Pdf_Page::SHAPE_DRAW_FILL_AND_STROKE - fill rectangle and stroke (default)
  6. * Zend_Pdf_Page::SHAPE_DRAW_STROKE      - stroke rectangle
  7. * Zend_Pdf_Page::SHAPE_DRAW_FILL        - fill rectangle
  8. *
  9. * radius is an integer representing radius of the four corners, or an array
  10. * of four integers representing the radius starting at top left, going
  11. * clockwise
  12. *
  13. * @param float $x1
  14. * @param float $y1
  15. * @param float $x2
  16. * @param float $y2
  17. * @param integer|array $radius
  18. * @param integer $fillType
  19. * @return Zend_Pdf_Page
  20. */
  21. public function drawRoundedRectangle($x1, $y1, $x2, $y2, $radius,
  22.                        $fillType = Zend_Pdf_Page::SHAPE_DRAW_FILL_AND_STROKE);
  1. /**
  2. * Draw a polygon.
  3. *
  4. * If $fillType is Zend_Pdf_Page::SHAPE_DRAW_FILL_AND_STROKE or
  5. * Zend_Pdf_Page::SHAPE_DRAW_FILL, then polygon is automatically closed.
  6. * See detailed description of these methods in a PDF documentation
  7. * (section 4.4.2 Path painting Operators, Filling)
  8. *
  9. * @param array $x  - array of float (the X co-ordinates of the vertices)
  10. * @param array $y  - array of float (the Y co-ordinates of the vertices)
  11. * @param integer $fillType
  12. * @param integer $fillMethod
  13. * @return Zend_Pdf_Page
  14. */
  15. public function drawPolygon($x, $y,
  16.                             $fillType =
  17.                                 Zend_Pdf_Page::SHAPE_DRAW_FILL_AND_STROKE,
  18.                             $fillMethod =
  19.                                 Zend_Pdf_Page::FILL_METHOD_NON_ZERO_WINDING);
  1. /**
  2. * Draw a circle centered on x, y with a radius of radius.
  3. *
  4. * Angles are specified in radians
  5. *
  6. * Method signatures:
  7. * drawCircle($x, $y, $radius);
  8. * drawCircle($x, $y, $radius, $fillType);
  9. * drawCircle($x, $y, $radius, $startAngle, $endAngle);
  10. * drawCircle($x, $y, $radius, $startAngle, $endAngle, $fillType);
  11. *
  12. *
  13. * It's not a really circle, because PDF supports only cubic Bezier
  14. * curves. But very good approximation.
  15. * It differs from a real circle on a maximum 0.00026 radiuses (at PI/8,
  16. * 3*PI/8, 5*PI/8, 7*PI/8, 9*PI/8, 11*PI/8, 13*PI/8 and 15*PI/8 angles).
  17. * At 0, PI/4, PI/2, 3*PI/4, PI, 5*PI/4, 3*PI/2 and 7*PI/4 it's exactly
  18. * a tangent to a circle.
  19. *
  20. * @param float $x
  21. * @param float $y
  22. * @param float $radius
  23. * @param mixed $param4
  24. * @param mixed $param5
  25. * @param mixed $param6
  26. * @return Zend_Pdf_Page
  27. */
  28. public function  drawCircle($x,
  29.                             $y,
  30.                             $radius,
  31.                             $param4 = null,
  32.                             $param5 = null,
  33.                             $param6 = null);
  1. /**
  2. * Draw an ellipse inside the specified rectangle.
  3. *
  4. * Method signatures:
  5. * drawEllipse($x1, $y1, $x2, $y2);
  6. * drawEllipse($x1, $y1, $x2, $y2, $fillType);
  7. * drawEllipse($x1, $y1, $x2, $y2, $startAngle, $endAngle);
  8. * drawEllipse($x1, $y1, $x2, $y2, $startAngle, $endAngle, $fillType);
  9. *
  10. * Angles are specified in radians
  11. *
  12. * @param float $x1
  13. * @param float $y1
  14. * @param float $x2
  15. * @param float $y2
  16. * @param mixed $param5
  17. * @param mixed $param6
  18. * @param mixed $param7
  19. * @return Zend_Pdf_Page
  20. */
  21. public function drawEllipse($x1,
  22.                             $y1,
  23.                             $x2,
  24.                             $y2,
  25.                             $param5 = null,
  26.                             $param6 = null,
  27.                             $param7 = null);

Text Drawing

Text drawing operations also exist in the context of a PDF page. You can draw a single line of text at any position on the page by supplying the x and y coordinates of the baseline. Current font and current font size are used for text drawing operations (see detailed description below).

  1. /**
  2. * Draw a line of text at the specified position.
  3. *
  4. * @param string $text
  5. * @param float $x
  6. * @param float $y
  7. * @param string $charEncoding (optional) Character encoding of source
  8. *               text.Defaults to current locale.
  9. * @throws Zend_Pdf_Exception
  10. * @return Zend_Pdf_Page
  11. */
  12. public function drawText($text, $x, $y, $charEncoding = '');

Example #1 Draw a string on the page

  1. ...
  2. $pdfPage->drawText('Hello world!', 72, 720);
  3. ...

By default, text strings are interpreted using the character encoding method of the current locale. If you have a string that uses a different encoding method (such as a UTF-8 string read from a file on disk, or a MacRoman string obtained from a legacy database), you can indicate the character encoding at draw time and Zend_Pdf will handle the conversion for you. You can supply source strings in any encoding method supported by PHP's » iconv() function:

Example #2 Draw a UTF-8-encoded string on the page

  1. ...
  2. // Read a UTF-8-encoded string from disk
  3. $unicodeString = fread($fp, 1024);
  4.
  5. // Draw the string on the page
  6. $pdfPage->drawText($unicodeString, 72, 720, 'UTF-8');
  7. ...

Using fonts

Zend_Pdf_Page::drawText() uses the page's current font and font size, which is set with the Zend_Pdf_Page::setFont() method:

  1. /**
  2. * Set current font.
  3. *
  4. * @param Zend_Pdf_Resource_Font $font
  5. * @param float $fontSize
  6. * @return Zend_Pdf_Page
  7. */
  8. public function setFont(Zend_Pdf_Resource_Font $font, $fontSize);

PDF documents support PostScript Type 1 and TrueType fonts, as well as two specialized PDF types, Type 3 and composite fonts. There are also 14 standard Type 1 fonts built-in to every PDF viewer: Courier (4 styles), Helvetica (4 styles), Times (4 styles), Symbol, and Zapf Dingbats.

Zend_Pdf currently supports the standard 14 PDF fonts as well as your own custom TrueType fonts. Font objects are obtained via one of two factory methods: Zend_Pdf_Font::fontWithName($fontName) for the standard 14 PDF fonts or Zend_Pdf_Font::fontWithPath($filePath) for custom fonts.

Example #3 Create a standard font

  1. ...
  2. // Create new font
  3. $font = Zend_Pdf_Font::fontWithName(Zend_Pdf_Font::FONT_HELVETICA);
  4.
  5. // Apply font
  6. $pdfPage->setFont($font, 36);
  7. ...

Constants for the standard 14 PDF font names are defined in the Zend_Pdf_Font class:

  • Zend_Pdf_Font::FONT_COURIER

  • Zend_Pdf_Font::FONT_COURIER_BOLD

  • Zend_Pdf_Font::FONT_COURIER_ITALIC

  • Zend_Pdf_Font::FONT_COURIER_BOLD_ITALIC

  • Zend_Pdf_Font::FONT_TIMES

  • Zend_Pdf_Font::FONT_TIMES_BOLD

  • Zend_Pdf_Font::FONT_TIMES_ITALIC

  • Zend_Pdf_Font::FONT_TIMES_BOLD_ITALIC

  • Zend_Pdf_Font::FONT_HELVETICA

  • Zend_Pdf_Font::FONT_HELVETICA_BOLD

  • Zend_Pdf_Font::FONT_HELVETICA_ITALIC

  • Zend_Pdf_Font::FONT_HELVETICA_BOLD_ITALIC

  • Zend_Pdf_Font::FONT_SYMBOL

  • Zend_Pdf_Font::FONT_ZAPFDINGBATS

You can also use any individual TrueType font (which usually has a '.ttf' extension) or an OpenType font ('.otf' extension) if it contains TrueType outlines. Currently unsupported, but planned for a future release are Mac OS X .dfont files and Microsoft TrueType Collection ('.ttc' extension) files.

To use a TrueType font, you must provide the full file path to the font program. If the font cannot be read for some reason, or if it is not a TrueType font, the factory method will throw an exception:

Example #4 Create a TrueType font

  1. ...
  2. // Create new font
  3. $goodDogCoolFont = Zend_Pdf_Font::fontWithPath('/path/to/GOODDC__.TTF');
  4.
  5. // Apply font
  6. $pdfPage->setFont($goodDogCoolFont, 36);
  7. ...

By default, custom fonts will be embedded in the resulting PDF document. This allows recipients to view the page as intended, even if they don't have the proper fonts installed on their system. If you are concerned about file size, you can request that the font program not be embedded by passing a 'do not embed' option to the factory method:

Example #5 Create a TrueType font, but do not embed it in the PDF document

  1. ...
  2. // Create new font
  3. $goodDogCoolFont = Zend_Pdf_Font::fontWithPath('/path/to/GOODDC__.TTF',
  4.                                                Zend_Pdf_Font::EMBED_DONT_EMBED);
  5.
  6. // Apply font
  7. $pdfPage->setFont($goodDogCoolFont, 36);
  8. ...

If the font program is not embedded but the recipient of the PDF file has the font installed on their system, they will see the document as intended. If they do not have the correct font installed, the PDF viewer application will do its best to synthesize a replacement.

Some fonts have very specific licensing rules which prevent them from being embedded in PDF documents. So you are not caught off-guard by this, if you try to use a font that cannot be embedded, the factory method will throw an exception.

You can still use these fonts, but you must either pass the do not embed flag as described above, or you can simply suppress the exception:

Example #6 Do not throw an exception for fonts that cannot be embedded

  1. ...
  2. $font = Zend_Pdf_Font::fontWithPath(
  3.            '/path/to/unEmbeddableFont.ttf',
  4.            Zend_Pdf_Font::EMBED_SUPPRESS_EMBED_EXCEPTION
  5.         );
  6. ...

This suppression technique is preferred if you allow an end-user to choose their own fonts. Fonts which can be embedded in the PDF document will be; those that cannot, won't.

Font programs can be rather large, some reaching into the tens of megabytes. By default, all embedded fonts are compressed using the Flate compression scheme, resulting in a space savings of 50% on average. If, for some reason, you do not want to compress the font program, you can disable it with an option:

Example #7 Do not compress an embedded font

  1. ...
  2. $font = Zend_Pdf_Font::fontWithPath('/path/to/someReallyBigFont.ttf',
  3.                                     Zend_Pdf_Font::EMBED_DONT_COMPRESS);
  4. ...

Finally, when necessary, you can combine the embedding options by using the bitwise OR operator:

Example #8 Combining font embedding options

  1. ...
  2. $font = Zend_Pdf_Font::fontWithPath(
  3.             $someUserSelectedFontPath,
  4.             (Zend_Pdf_Font::EMBED_SUPPRESS_EMBED_EXCEPTION |
  5.             Zend_Pdf_Font::EMBED_DONT_COMPRESS));
  6. ...

Standard PDF fonts limitations

Standard PDF fonts use several single byte encodings internally (see » PDF Reference, Sixth Edition, version 1.7 Appendix D for details). They are generally equal to Latin1 character set (except Symbol and ZapfDingbats fonts).

Zend_Pdf uses CP1252 (WinLatin1) for drawing text with standard fonts.

Text still can be provided in any other encoding, which must be specified if it differs from a current locale. Only WinLatin1 characters will be actually drawn.

Example #9 Combining font embedding options

  1. ...
  2. $font = Zend_Pdf_Font::fontWithName(Zend_Pdf_Font::FONT_COURIER);
  3. $pdfPage->setFont($font, 36)
  4.         ->drawText('Euro sign - €', 72, 720, 'UTF-8')
  5.         ->drawText('Text with umlauts - à è ì', 72, 650, 'UTF-8');
  6. ...

Extracting fonts

Zend_Pdf module provides a possibility to extract fonts from loaded documents.

It may be useful for incremental document updates. Without this functionality you have to attach and possibly embed font into a document each time you want to update it.

Zend_Pdf and Zend_Pdf_Page objects provide special methods to extract all fonts mentioned within a document or a page:

Example #10 Extracting fonts from a loaded document

  1. ...
  2. $pdf = Zend_Pdf::load($documentPath);
  3. ...
  4. // Get all document fonts
  5. $fontList = $pdf->extractFonts();
  6. $pdf->pages[] = ($page = $pdf->newPage(Zend_Pdf_Page::SIZE_A4));
  7. $yPosition = 700;
  8. foreach ($fontList as $font) {
  9.     $page->setFont($font, 15);
  10.     $fontName = $font->getFontName(Zend_Pdf_Font::NAME_POSTSCRIPT,
  11.                                    'en',
  12.                                    'UTF-8');
  13.     $page->drawText($fontName . ': The quick brown fox jumps over the lazy dog',
  14.                     100,
  15.                     $yPosition,
  16.                     'UTF-8');
  17.     $yPosition -= 30;
  18. }
  19. ...
  20. // Get fonts referenced within the first document page
  21. $firstPage = reset($pdf->pages);
  22. $firstPageFonts = $firstPage->extractFonts();
  23. ...

Example #11 Extracting font from a loaded document by specifying font name

  1. ...
  2. $pdf = new Zend_Pdf();
  3. ...
  4. $pdf->pages[] = ($page = $pdf->newPage(Zend_Pdf_Page::SIZE_A4));
  5.
  6. $font = Zend_Pdf_Font::fontWithPath($fontPath);
  7. $page->setFont($font, $fontSize);
  8. $page->drawText($text, $x, $y);
  9. ...
  10. // This font name should be stored somewhere...
  11. $fontName = $font->getFontName(Zend_Pdf_Font::NAME_POSTSCRIPT,
  12.                                'en',
  13.                                'UTF-8');
  14. ...
  15. $pdf->save($docPath);
  16. ...
  1. ...
  2. $pdf = Zend_Pdf::load($docPath);
  3. ...
  4. $pdf->pages[] = ($page = $pdf->newPage(Zend_Pdf_Page::SIZE_A4));
  5.
  6. /* $srcPage->extractFont($fontName) can also be used here */
  7. $font = $pdf->extractFont($fontName);
  8.
  9. $page->setFont($font, $fontSize);
  10. $page->drawText($text, $x, $y);
  11. ...
  12. $pdf->save($docPath, true /* incremental update mode */);
  13. ...

Extracted fonts can be used in the place of any other font with the following limitations:

  • Extracted font can be used only in the context of the document from which it was extracted.

  • Possibly embedded font program is actually not extracted. So extracted font can't provide correct font metrics and original font has to be used for text width calculations:

    1. ...
    2. $font = $pdf->extractFont($fontName);
    3. $originalFont = Zend_Pdf_Font::fontWithPath($fontPath);
    4.
    5. $page->setFont($font /* use extracted font for drawing */, $fontSize);
    6. $xPosition = $x;
    7. for ($charIndex = 0; $charIndex < strlen($text); $charIndex++) {
    8.     $page->drawText($text[$charIndex], xPosition, $y);
    9.
    10.     // Use original font for text width calculation
    11.     $width = $originalFont->widthForGlyph(
    12.                  $originalFont->glyphNumberForCharacter($text[$charIndex])
    13.              );
    14.     $xPosition += $width/$originalFont->getUnitsPerEm()*$fontSize;
    15. }
    16. ...

Image Drawing

Zend_Pdf_Page class provides drawImage() method to draw image:

  1. /**
  2. * Draw an image at the specified position on the page.
  3. *
  4. * @param Zend_Pdf_Resource_Image $image
  5. * @param float $x1
  6. * @param float $y1
  7. * @param float $x2
  8. * @param float $y2
  9. * @return Zend_Pdf_Page
  10. */
  11. public function drawImage(Zend_Pdf_Resource_Image $image, $x1, $y1, $x2, $y2);

Image objects should be created with Zend_Pdf_Image::imageWithPath($filePath) method (JPG, PNG and TIFF images are supported now):

Example #12 Image drawing

  1. ...
  2. // load image
  3. $image = Zend_Pdf_Image::imageWithPath('my_image.jpg');
  4.
  5. $pdfPage->drawImage($image, 100, 100, 400, 300);
  6. ...

Important! JPEG support requires PHP GD extension to be configured. Important! PNG support requires ZLIB extension to be configured to work with Alpha channel images.

Refer to the PHP documentation for detailed information (» http://www.php.net/manual/en/ref.image.php). (» http://www.php.net/manual/en/ref.zlib.php).

Line drawing style

Line drawing style is defined by line width, line color and line dashing pattern. All of this parameters can be assigned by Zend_Pdf_Page class methods:

  1. /** Set line color. */
  2. public function setLineColor(Zend_Pdf_Color $color);
  3.
  4. /** Set line width. */
  5. public function setLineWidth(float $width);
  6.
  7. /**
  8. * Set line dashing pattern.
  9. *
  10. * Pattern is an array of floats:
  11. *     array(on_length, off_length, on_length, off_length, ...)
  12. * Phase is shift from the beginning of line.
  13. *
  14. * @param array $pattern
  15. * @param array $phase
  16. * @return Zend_Pdf_Page
  17. */
  18. public function setLineDashingPattern($pattern, $phase = 0);

Fill style

Zend_Pdf_Page::drawRectangle(), Zend_Pdf_Page::drawPolygon(), Zend_Pdf_Page::drawCircle() and Zend_Pdf_Page::drawEllipse() methods take $fillType argument as an optional parameter. It can be:

  • Zend_Pdf_Page::SHAPE_DRAW_STROKE - stroke shape

  • Zend_Pdf_Page::SHAPE_DRAW_FILL - only fill shape

  • Zend_Pdf_Page::SHAPE_DRAW_FILL_AND_STROKE - fill and stroke (default behavior)

Zend_Pdf_Page::drawPolygon() methods also takes an additional parameter $fillMethod:

  • Zend_Pdf_Page::FILL_METHOD_NON_ZERO_WINDING (default behavior)

    PDF reference describes this rule as follows:

    The nonzero winding number rule determines whether a given point is inside a path by conceptually drawing a ray from that point to infinity in any direction and then examining the places where a segment of the path crosses the ray. Starting with a count of 0, the rule adds 1 each time a path segment crosses the ray from left to right and subtracts 1 each time a segment crosses from right to left. After counting all the crossings, if the result is 0 then the point is outside the path; otherwise it is inside. Note: The method just described does not specify what to do if a path segment coincides with or is tangent to the chosen ray. Since the direction of the ray is arbitrary, the rule simply chooses a ray that does not encounter such problem intersections. For simple convex paths, the nonzero winding number rule defines the inside and outside as one would intuitively expect. The more interesting cases are those involving complex or self-intersecting paths like the ones shown in Figure 4.10 (in a PDF Reference). For a path consisting of a five-pointed star, drawn with five connected straight line segments intersecting each other, the rule considers the inside to be the entire area enclosed by the star, including the pentagon in the center. For a path composed of two concentric circles, the areas enclosed by both circles are considered to be inside, provided that both are drawn in the same direction. If the circles are drawn in opposite directions, only the "doughnut" shape between them is inside, according to the rule; the "doughnut hole" is outside.

  • Zend_Pdf_Page::FILL_METHOD_EVEN_ODD

    PDF reference describes this rule as follows:

    An alternative to the nonzero winding number rule is the even-odd rule. This rule determines the "insideness" of a point by drawing a ray from that point in any direction and simply counting the number of path segments that cross the ray, regardless of direction. If this number is odd, the point is inside; if even, the point is outside. This yields the same results as the nonzero winding number rule for paths with simple shapes, but produces different results for more complex shapes. Figure 4.11 (in a PDF Reference) shows the effects of applying the even-odd rule to complex paths. For the five-pointed star, the rule considers the triangular points to be inside the path, but not the pentagon in the center. For the two concentric circles, only the "doughnut" shape between the two circles is considered inside, regardless of the directions in which the circles are drawn.

Linear Transformations

Rotations

PDF page can be rotated before applying any draw operation. It can be done by Zend_Pdf_Page::rotate() method:

  1. /**
  2. * Rotate the page.
  3. *
  4. * @param float $x  - the X co-ordinate of rotation point
  5. * @param float $y  - the Y co-ordinate of rotation point
  6. * @param float $angle - rotation angle
  7. * @return Zend_Pdf_Page
  8. */
  9. public function rotate($x, $y, $angle);

Starting from ZF 1.8, scaling

Scaling transformation is provided by Zend_Pdf_Page::scale() method:

  1. /**
  2. * Scale coordination system.
  3. *
  4. * @param float $xScale - X dimention scale factor
  5. * @param float $yScale - Y dimention scale factor
  6. * @return Zend_Pdf_Page
  7. */
  8. public function scale($xScale, $yScale);

Starting from ZF 1.8, translating

Coordinate system shifting is performed by Zend_Pdf_Page::translate() method:

  1. /**
  2. * Translate coordination system.
  3. *
  4. * @param float $xShift - X coordinate shift
  5. * @param float $yShift - Y coordinate shift
  6. * @return Zend_Pdf_Page
  7. */
  8. public function translate($xShift, $yShift);

Starting from ZF 1.8, skewing

Page skewing can be done using Zend_Pdf_Page::skew() method:

  1. /**
  2. * Translate coordination system.
  3. *
  4. * @param float $x  - the X co-ordinate of axis skew point
  5. * @param float $y  - the Y co-ordinate of axis skew point
  6. * @param float $xAngle - X axis skew angle
  7. * @param float $yAngle - Y axis skew angle
  8. * @return Zend_Pdf_Page
  9. */
  10. public function skew($x, $y, $xAngle, $yAngle);

Save/restore graphics state

At any time page graphics state (current font, font size, line color, fill color, line style, page rotation, clip area) can be saved and then restored. Save operation puts data to a graphics state stack, restore operation retrieves it from there.

There are two methods in Zend_Pdf_Page class for these operations:

  1. /**
  2. * Save the graphics state of this page.
  3. * This takes a snapshot of the currently applied style, position,
  4. * clipping area and any rotation/translation/scaling that has been
  5. * applied.
  6. *
  7. * @return Zend_Pdf_Page
  8. */
  9. public function saveGS();
  10.
  11. /**
  12. * Restore the graphics state that was saved with the last call to
  13. * saveGS().
  14. *
  15. * @return Zend_Pdf_Page
  16. */
  17. public function restoreGS();

Clipping draw area

PDF and Zend_Pdf module support clipping of draw area. Current clip area limits the regions of the page affected by painting operators. It's a whole page initially.

Zend_Pdf_Page class provides a set of methods for clipping operations.

  1. /**
  2. * Intersect current clipping area with a rectangle.
  3. *
  4. * @param float $x1
  5. * @param float $y1
  6. * @param float $x2
  7. * @param float $y2
  8. * @return Zend_Pdf_Page
  9. */
  10. public function clipRectangle($x1, $y1, $x2, $y2);
  1. /**
  2. * Intersect current clipping area with a polygon.
  3. *
  4. * @param array $x  - array of float (the X co-ordinates of the vertices)
  5. * @param array $y  - array of float (the Y co-ordinates of the vertices)
  6. * @param integer $fillMethod
  7. * @return Zend_Pdf_Page
  8. */
  9. public function clipPolygon($x,
  10.                             $y,
  11.                             $fillMethod =
  12.                                 Zend_Pdf_Page::FILL_METHOD_NON_ZERO_WINDING);
  1. /**
  2. * Intersect current clipping area with a circle.
  3. *
  4. * @param float $x
  5. * @param float $y
  6. * @param float $radius
  7. * @param float $startAngle
  8. * @param float $endAngle
  9. * @return Zend_Pdf_Page
  10. */
  11. public function clipCircle($x,
  12.                            $y,
  13.                            $radius,
  14.                            $startAngle = null,
  15.                            $endAngle = null);
  1. /**
  2. * Intersect current clipping area with an ellipse.
  3. *
  4. * Method signatures:
  5. * drawEllipse($x1, $y1, $x2, $y2);
  6. * drawEllipse($x1, $y1, $x2, $y2, $startAngle, $endAngle);
  7. *
  8. * @todo process special cases with $x2-$x1 == 0 or $y2-$y1 == 0
  9. *
  10. * @param float $x1
  11. * @param float $y1
  12. * @param float $x2
  13. * @param float $y2
  14. * @param float $startAngle
  15. * @param float $endAngle
  16. * @return Zend_Pdf_Page
  17. */
  18. public function clipEllipse($x1,
  19.                             $y1,
  20.                             $x2,
  21.                             $y2,
  22.                             $startAngle = null,
  23.                             $endAngle = null);

Styles

Zend_Pdf_Style class provides styles functionality.

Styles can be used to store a set of graphic state parameters and apply it to a PDF page by one operation:

  1. /**
  2. * Set the style to use for future drawing operations on this page
  3. *
  4. * @param Zend_Pdf_Style $style
  5. * @return Zend_Pdf_Page
  6. */
  7. public function setStyle(Zend_Pdf_Style $style);
  8.
  9. /**
  10. * Return the style, applied to the page.
  11. *
  12. * @return Zend_Pdf_Style|null
  13. */
  14. public function getStyle();

Zend_Pdf_Style class provides a set of methods to set or get different graphics state parameters:

  1. /**
  2. * Set line color.
  3. *
  4. * @param Zend_Pdf_Color $color
  5. * @return Zend_Pdf_Page
  6. */
  7. public function setLineColor(Zend_Pdf_Color $color);
  1. /**
  2. * Get line color.
  3. *
  4. * @return Zend_Pdf_Color|null
  5. */
  6. public function getLineColor();
  1. /**
  2. * Set line width.
  3. *
  4. * @param float $width
  5. * @return Zend_Pdf_Page
  6. */
  7. public function setLineWidth($width);
  1. /**
  2. * Get line width.
  3. *
  4. * @return float
  5. */
  6. public function getLineWidth();
  1. /**
  2. * Set line dashing pattern
  3. *
  4. * @param array $pattern
  5. * @param float $phase
  6. * @return Zend_Pdf_Page
  7. */
  8. public function setLineDashingPattern($pattern, $phase = 0);
  1. /**
  2. * Get line dashing pattern
  3. *
  4. * @return array
  5. */
  6. public function getLineDashingPattern();
  1. /**
  2. * Get line dashing phase
  3. *
  4. * @return float
  5. */
  6. public function getLineDashingPhase();
  1. /**
  2. * Set fill color.
  3. *
  4. * @param Zend_Pdf_Color $color
  5. * @return Zend_Pdf_Page
  6. */
  7. public function setFillColor(Zend_Pdf_Color $color);
  1. /**
  2. * Get fill color.
  3. *
  4. * @return Zend_Pdf_Color|null
  5. */
  6. public function getFillColor();
  1. /**
  2. * Set current font.
  3. *
  4. * @param Zend_Pdf_Resource_Font $font
  5. * @param float $fontSize
  6. * @return Zend_Pdf_Page
  7. */
  8. public function setFont(Zend_Pdf_Resource_Font $font, $fontSize);
  1. /**
  2. * Modify current font size
  3. *
  4. * @param float $fontSize
  5. * @return Zend_Pdf_Page
  6. */
  7. public function setFontSize($fontSize);
  1. /**
  2. * Get current font.
  3. *
  4. * @return Zend_Pdf_Resource_Font $font
  5. */
  6. public function getFont();
  1. /**
  2. * Get current font size
  3. *
  4. * @return float $fontSize
  5. */
  6. public function getFontSize();

Transparency

Zend_Pdf module supports transparency handling.

Transparency may be set using Zend_Pdf_Page::setAlpha() method:

  1. /**
  2. * Set the transparency
  3. *
  4. * $alpha == 0  - transparent
  5. * $alpha == 1  - opaque
  6. *
  7. * Transparency modes, supported by PDF:
  8. * Normal (default), Multiply, Screen, Overlay, Darken, Lighten,
  9. * ColorDodge, ColorBurn, HardLight, SoftLight, Difference, Exclusion
  10. *
  11. * @param float $alpha
  12. * @param string $mode
  13. * @throws Zend_Pdf_Exception
  14. * @return Zend_Pdf_Page
  15. */
  16. public function setAlpha($alpha, $mode = 'Normal');

文档页面
Zend_Pdf
Zend Framework手册 中文版
Interactive Features
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Pdf
  • 简介
  • 生成和加载 PDF 文档
  • 保存修改到 PDF 文档
  • 文档页面
  • Drawing
  • Interactive Features
  • Document Info and Metadata
  • Zend_Pdf module usage example


Interactive Features - Zend Framework Manual

Drawing
Zend_Pdf
Zend Framework手册 中文版
Document Info and Metadata

Interactive Features

Destinations

A destination defines a particular view of a document, consisting of the following items:

  • The page of the document to be displayed.

  • The location of the document window on that page.

  • The magnification (zoom) factor to use when displaying the page.

Destinations may be associated with outline items (Document Outline (bookmarks)), annotations (Annotations), or actions (Actions). In each case, the destination specifies the view of the document to be presented when the outline item or annotation is opened or the action is performed. In addition, the optional document open action can be specified.

Supported Destination Types

The following types are supported by Zend_Pdf component.

Zend_Pdf_Destination_Zoom

Display the specified page, with the coordinates (left, top) positioned at the upper-left corner of the window and the contents of the page magnified by the factor zoom.

Destination object may be created using Zend_Pdf_Destination_Zoom::create($page, $left = null, $top = null, $zoom = null) method.

Where:

  • $page is a destination page (a Zend_Pdf_Page object or a page number).

  • $left is a left edge of the displayed page (float).

  • $top is a top edge of the displayed page (float).

  • $zoom is a zoom factor (float).

NULL, specified for $left, $top or $zoom parameter means "current viewer application value".

Zend_Pdf_Destination_Zoom class also provides the following methods:

  • Float getLeftEdge();

  • setLeftEdge(float $left);

  • Float getTopEdge();

  • setTopEdge(float $top);

  • Float getZoomFactor();

  • setZoomFactor(float $zoom);

Zend_Pdf_Destination_Fit

Display the specified page, with the coordinates (left, top) positioned at the upper-left corner of the window and the contents of the page magnified by the factor zoom. Display the specified page, with its contents magnified just enough to fit the entire page within the window both horizontally and vertically. If the required horizontal and vertical magnification factors are different, use the smaller of the two, centering the page within the window in the other dimension.

Destination object may be created using Zend_Pdf_Destination_Fit::create($page) method.

Where $page is a destination page (a Zend_Pdf_Page object or a page number).

Zend_Pdf_Destination_FitHorizontally

Display the specified page, with the vertical coordinate top positioned at the top edge of the window and the contents of the page magnified just enough to fit the entire width of the page within the window.

Destination object may be created using Zend_Pdf_Destination_FitHorizontally::create($page, $top) method.

Where:

  • $page is a destination page (a Zend_Pdf_Page object or a page number).

  • $top is a top edge of the displayed page (float).

Zend_Pdf_Destination_FitHorizontally class also provides the following methods:

  • Float getTopEdge();

  • setTopEdge(float $top);

Zend_Pdf_Destination_FitVertically

Display the specified page, with the horizontal coordinate left positioned at the left edge of the window and the contents of the page magnified just enough to fit the entire height of the page within the window.

Destination object may be created using Zend_Pdf_Destination_FitVertically::create($page, $left) method.

Where:

  • $page is a destination page (a Zend_Pdf_Page object or a page number).

  • $left is a left edge of the displayed page (float).

Zend_Pdf_Destination_FitVertically class also provides the following methods:

  • Float getLeftEdge();

  • setLeftEdge(float $left);

Zend_Pdf_Destination_FitRectangle

Display the specified page, with its contents magnified just enough to fit the rectangle specified by the coordinates left, bottom, right, and top entirely within the window both horizontally and vertically. If the required horizontal and vertical magnification factors are different, use the smaller of the two, centering the rectangle within the window in the other dimension.

Destination object may be created using Zend_Pdf_Destination_FitRectangle::create($page, $left, $bottom, $right, $top) method.

Where:

  • $page is a destination page (a Zend_Pdf_Page object or a page number).

  • $left is a left edge of the displayed page (float).

  • $bottom is a bottom edge of the displayed page (float).

  • $right is a right edge of the displayed page (float).

  • $top is a top edge of the displayed page (float).

Zend_Pdf_Destination_FitRectangle class also provides the following methods:

  • Float getLeftEdge();

  • setLeftEdge(float $left);

  • Float getBottomEdge();

  • setBottomEdge(float $bottom);

  • Float getRightEdge();

  • setRightEdge(float $right);

  • Float getTopEdge();

  • setTopEdge(float $top);

Zend_Pdf_Destination_FitBoundingBox

Display the specified page, with its contents magnified just enough to fit its bounding box entirely within the window both horizontally and vertically. If the required horizontal and vertical magnification factors are different, use the smaller of the two, centering the bounding box within the window in the other dimension.

Destination object may be created using Zend_Pdf_Destination_FitBoundingBox::create($page, $left, $bottom, $right, $top) method.

Where $page is a destination page (a Zend_Pdf_Page object or a page number).

Zend_Pdf_Destination_FitBoundingBoxHorizontally

Display the specified page, with the vertical coordinate top positioned at the top edge of the window and the contents of the page magnified just enough to fit the entire width of its bounding box within the window.

Destination object may be created using Zend_Pdf_Destination_FitBoundingBoxHorizontally::create($page, $top) method.

Where

  • $page is a destination page (a Zend_Pdf_Page object or a page number).

  • $top is a top edge of the displayed page (float).

Zend_Pdf_Destination_FitBoundingBoxHorizontally class also provides the following methods:

  • Float getTopEdge();

  • setTopEdge(float $top);

Zend_Pdf_Destination_FitBoundingBoxVertically

Display the specified page, with the horizontal coordinate left positioned at the left edge of the window and the contents of the page magnified just enough to fit the entire height of its bounding box within the window.

Destination object may be created using Zend_Pdf_Destination_FitBoundingBoxVertically::create($page, $left) method.

Where

  • $page is a destination page (a Zend_Pdf_Page object or a page number).

  • $left is a left edge of the displayed page (float).

Zend_Pdf_Destination_FitBoundingBoxVertically class also provides the following methods:

  • Float getLeftEdge();

  • setLeftEdge(float $left);

Zend_Pdf_Destination_Named

All destinations listed above are "Explicit Destinations".

In addition to this, PDF document may contain a dictionary of such destinations which may be used to reference from outside the PDF (e.g. 'http://www.mycompany.com/document.pdf#chapter3').

Zend_Pdf_Destination_Named objects allow to refer destinations from the document named destinations dictionary.

Named destination object may be created using Zend_Pdf_Destination_Named::create(string $name) method.

Zend_Pdf_Destination_Named class provides the only one additional method:

String getName();

Document level destination processing

Zend_Pdf class provides a set of destinations processing methods.

Each destination object (including named destinations) can be resolved using the resolveDestination($destination) method. It returns corresponding Zend_Pdf_Page object, if destination target is found, or NULL otherwise.

Zend_Pdf::resolveDestination() method also takes an optional boolean parameter $refreshPageCollectionHashes, which is TRUE by default. It forces Zend_Pdf object to refresh internal page collection hashes since document pages list may be updated by user using Zend_Pdf::$pages property (Working with Pages). It may be turned off for performance reasons, if it's known that document pages list wasn't changed since last method request.

Complete list of named destinations can be retrieved using Zend_Pdf::getNamedDestinations() method. It returns an array of Zend_Pdf_Target objects, which are actually either an explicit destination or a GoTo action (Actions).

Zend_Pdf::getNamedDestination(string $name) method returns specified named destination (an explicit destination or a GoTo action).

PDF document named destinations dictionary may be updated with Zend_Pdf::setNamedDestination(string $name, $destination) method, where $destination is either an explicit destination (any destination except Zend_Pdf_Destination_Named) or a GoTo action.

If NULL is specified in place of $destination, then specified named destination is removed.

Note: Unresolvable named destinations are automatically removed from a document while document saving.

Example #1 Destinations usage example

  1. $pdf = new Zend_Pdf();
  2. $page1 = $pdf->newPage(Zend_Pdf_Page::SIZE_A4);
  3. $page2 = $pdf->newPage(Zend_Pdf_Page::SIZE_A4);
  4. $page3 = $pdf->newPage(Zend_Pdf_Page::SIZE_A4);
  5. // Page created, but not included into pages list
  6.
  7. $pdf->pages[] = $page1;
  8. $pdf->pages[] = $page2;
  9.
  10. $destination1 = Zend_Pdf_Destination_Fit::create($page2);
  11. $destination2 = Zend_Pdf_Destination_Fit::create($page3);
  12.
  13. // Returns $page2 object
  14. $page = $pdf->resolveDestination($destination1);
  15.
  16. // Returns null, page 3 is not included into document yet
  17. $page = $pdf->resolveDestination($destination2);
  18.
  19. $pdf->setNamedDestination('Page2', $destination1);
  20. $pdf->setNamedDestination('Page3', $destination2);
  21.
  22. // Returns $destination2
  23. $destination = $pdf->getNamedDestination('Page3');
  24.
  25. // Returns $destination1
  26. $pdf->resolveDestination(Zend_Pdf_Destination_Named::create('Page2'));
  27.
  28. // Returns null, page 3 is not included into document yet
  29. $pdf->resolveDestination(Zend_Pdf_Destination_Named::create('Page3'));

Actions

Instead of simply jumping to a destination in the document, an annotation or outline item can specify an action for the viewer application to perform, such as launching an application, playing a sound, or changing an annotation's appearance state.

Supported action types

The following action types are recognized while loading PDF document:

  • Zend_Pdf_Action_GoTo - go to a destination in the current document.

  • Zend_Pdf_Action_GoToR - go to a destination in another document.

  • Zend_Pdf_Action_GoToE - go to a destination in an embedded file.

  • Zend_Pdf_Action_Launch - launch an application or open or print a document.

  • Zend_Pdf_Action_Thread - begin reading an article thread.

  • Zend_Pdf_Action_URI - resolve a URI.

  • Zend_Pdf_Action_Sound - play a sound.

  • Zend_Pdf_Action_Movie - play a movie.

  • Zend_Pdf_Action_Hide - hides or shows one or more annotations on the screen.

  • Zend_Pdf_Action_Named - execute an action predefined by the viewer application:

    • NextPage - Go to the next page of the document.

    • PrevPage - Go to the previous page of the document.

    • FirstPage - Go to the first page of the document.

    • LastPage - Go to the last page of the document.

  • Zend_Pdf_Action_SubmitForm - send data to a uniform resource locator.

  • Zend_Pdf_Action_ResetForm - set fields to their default values.

  • Zend_Pdf_Action_ImportData - import field values from a file.

  • Zend_Pdf_Action_JavaScript - execute a JavaScript script.

  • Zend_Pdf_Action_SetOCGState - set the state of one or more optional content groups.

  • Zend_Pdf_Action_Rendition - control the playing of multimedia content (begin, stop, pause, or resume a playing rendition).

  • Zend_Pdf_Action_Trans - update the display of a document, using a transition dictionary.

  • Zend_Pdf_Action_GoTo3DView - set the current view of a 3D annotation.

Only Zend_Pdf_Action_GoTo and Zend_Pdf_Action_URI actions can be created by user now.

GoTo action object can be created using Zend_Pdf_Action_GoTo::create($destination) method, where $destination is a Zend_Pdf_Destination object or a string which can be used to identify named destination.

Zend_Pdf_Action_URI::create($uri[, $isMap]) method has to be used to create a URI action (see API documentation for the details). Optional $isMap parameter is set to FALSE by default.

It also supports the following methods:

Actions chaining

Actions objects can be chained using Zend_Pdf_Action::$next public property.

It's an array of Zend_Pdf_Action objects, which also may have their sub-actions.

Zend_Pdf_Action class supports RecursiveIterator interface, so child actions may be iterated recursively:

  1. $pdf = new Zend_Pdf();
  2. $page1 = $pdf->newPage(Zend_Pdf_Page::SIZE_A4);
  3. $page2 = $pdf->newPage(Zend_Pdf_Page::SIZE_A4);
  4. // Page created, but not included into pages list
  5. $page3 = $pdf->newPage(Zend_Pdf_Page::SIZE_A4);
  6.
  7. $pdf->pages[] = $page1;
  8. $pdf->pages[] = $page2;
  9.
  10. $action1 = Zend_Pdf_Action_GoTo::create(
  11.                             Zend_Pdf_Destination_Fit::create($page2));
  12. $action2 = Zend_Pdf_Action_GoTo::create(
  13.                             Zend_Pdf_Destination_Fit::create($page3));
  14. $action3 = Zend_Pdf_Action_GoTo::create(
  15.                             Zend_Pdf_Destination_Named::create('Chapter1'));
  16. $action4 = Zend_Pdf_Action_GoTo::create(
  17.                             Zend_Pdf_Destination_Named::create('Chapter5'));
  18.
  19. $action2->next[] = $action3;
  20. $action2->next[] = $action4;
  21.
  22. $action1->next[] = $action2;
  23.
  24. $actionsCount = 1; // Note! Iteration doesn't include top level action and
  25.                    // walks through children only
  26. $iterator = new RecursiveIteratorIterator(
  27.                                         $action1,
  28.                                         RecursiveIteratorIterator::SELF_FIRST);
  29. foreach ($iterator as $chainedAction) {
  30.     $actionsCount++;
  31. }
  32.
  33. // Prints 'Actions in a tree: 4'
  34. printf("Actions in a tree: %d\n", $actionsCount++);

Document Open Action

Special open action may be specify a destination to be displayed or an action to be performed when the document is opened.

Zend_Pdf_Target Zend_Pdf::getOpenAction() method returns current document open action (or NULL if open action is not set).

setOpenAction(Zend_Pdf_Target $openAction = null) method sets document open action or clean it if $openAction is NULL.

Document Outline (bookmarks)

A PDF document may optionally display a document outline on the screen, allowing the user to navigate interactively from one part of the document to another. The outline consists of a tree-structured hierarchy of outline items (sometimes called bookmarks), which serve as a visual table of contents to display the document's structure to the user. The user can interactively open and close individual items by clicking them with the mouse. When an item is open, its immediate children in the hierarchy become visible on the screen; each child may in turn be open or closed, selectively revealing or hiding further parts of the hierarchy. When an item is closed, all of its descendants in the hierarchy are hidden. Clicking the text of any visible item activates the item, causing the viewer application to jump to a destination or trigger an action associated with the item.

Zend_Pdf class provides public property $outlines which is an array of Zend_Pdf_Outline objects.

  1. $pdf = Zend_Pdf::load($path);
  2.
  3. // Remove outline item
  4. unset($pdf->outlines[0]->childOutlines[1]);
  5.
  6. // Set Outline to be displayed in bold
  7. $pdf->outlines[0]->childOutlines[3]->setIsBold(true);
  8.
  9. // Add outline entry
  10. $pdf->outlines[0]->childOutlines[5]->childOutlines[] =
  11.     Zend_Pdf_Outline::create('Chapter 2', 'chapter_2');
  12.
  13. $pdf->save($path, true);

Outline attributes may be retrieved or set using the following methods:

  • string getTitle() - get outline item title.

  • setTitle(string $title) - set outline item title.

  • boolean isOpen() - TRUE if outline is open by default.

  • setIsOpen(boolean $isOpen) - set isOpen state.

  • boolean isItalic() - TRUE if outline item is displayed in italic.

  • setIsItalic(boolean $isItalic) - set isItalic state.

  • boolean isBold() - TRUE if outline item is displayed in bold.

  • setIsBold(boolean $isBold) - set isBold state.

  • Zend_Pdf_Color_Rgb getColor() - get outline text color (NULL means black).

  • setColor(Zend_Pdf_Color_Rgb $color) - set outline text color (NULL means black).

  • Zend_Pdf_Target getTarget() - get outline target (action or explicit or named destination object).

  • setTarget(Zend_Pdf_Target|string $target) - set outline target (action or destination). String may be used to identify named destination. NULL means 'no target'.

  • array getOptions() - get outline attributes as an array.

  • setOptions(array $options) - set outline options. The following options are recognized: 'title', 'open', 'color', 'italic', 'bold', and 'target'.

New outline may be created in two ways:

  • Zend_Pdf_Outline::create(string $title[, Zend_Pdf_Target|string $target])

  • Zend_Pdf_Outline::create(array $options)

Each outline object may have child outline items listed in Zend_Pdf_Outline::$childOutlines public property. It's an array of Zend_Pdf_Outline objects, so outlines are organized in a tree.

Zend_Pdf_Outline class implements RecursiveArray interface, so child outlines may be recursively iterated using RecursiveIteratorIterator:

  1. $pdf = Zend_Pdf::load($path);
  2.
  3. foreach ($pdf->outlines as $documentRootOutlineEntry) {
  4.     $iterator = new RecursiveIteratorIterator(
  5.                     $documentRootOutlineEntry,
  6.                     RecursiveIteratorIterator::SELF_FIRST
  7.                 );
  8.     foreach ($iterator as $childOutlineItem) {
  9.         $OutlineItemTarget = $childOutlineItem->getTarget();
  10.         if ($OutlineItemTarget instanceof Zend_Pdf_Destination) {
  11.             if ($pdf->resolveDestination($OutlineItemTarget) === null) {
  12.                 // Mark Outline item with unresolvable destination
  13.                 // using RED color
  14.                 $childOutlineItem->setColor(new Zend_Pdf_Color_Rgb(1, 0, 0));
  15.             }
  16.         } else if ($OutlineItemTarget instanceof Zend_Pdf_Action_GoTo) {
  17.             $OutlineItemTarget->setDestination();
  18.             if ($pdf->resolveDestination($OutlineItemTarget) === null) {
  19.                 // Mark Outline item with unresolvable destination
  20.                 // using RED color
  21.                 $childOutlineItem->setColor(new Zend_Pdf_Color_Rgb(1, 0, 0));
  22.             }
  23.         }
  24.     }
  25. }
  26.
  27. $pdf->save($path, true);

Note: All outline items with unresolved destinations (or destinations of GoTo actions) are updated while document saving by setting their targets to NULL. So document will not be corrupted by removing pages referenced by outlines.

Annotations

An annotation associates an object such as a note, sound, or movie with a location on a page of a PDF document, or provides a way to interact with the user by means of the mouse and keyboard.

All annotations are represented by Zend_Pdf_Annotation abstract class.

Annotation may be attached to a page using Zend_Pdf_Page::attachAnnotation(Zend_Pdf_Annotation $annotation) method.

Three types of annotations may be created by user now:

  • Zend_Pdf_Annotation_Link::create($x1, $y1, $x2, $y2, $target) where $target is an action object or a destination or string (which may be used in place of named destination object).

  • Zend_Pdf_Annotation_Text::create($x1, $y1, $x2, $y2, $text)

  • Zend_Pdf_Annotation_FileAttachment::create($x1, $y1, $x2, $y2, $fileSpecification)

A link annotation represents either a hypertext link to a destination elsewhere in the document or an action to be performed.

A text annotation represents a "sticky note" attached to a point in the PDF document.

A file attachment annotation contains a reference to a file.

The following methods are shared between all annotation types:

  • setLeft(float $left)

  • float getLeft()

  • setRight(float $right)

  • float getRight()

  • setTop(float $top)

  • float getTop()

  • setBottom(float $bottom)

  • float getBottom()

  • setText(string $text)

  • string getText()

Text annotation property is a text to be displayed for the annotation or, if this type of annotation does not display text, an alternate description of the annotation's contents in human-readable form.

Link annotation objects also provide two additional methods:

  • setDestination(Zend_Pdf_Target|string $target)

  • Zend_Pdf_Target getDestination()

Drawing
Zend_Pdf
Zend Framework手册 中文版
Document Info and Metadata
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Pdf
  • 简介
  • 生成和加载 PDF 文档
  • 保存修改到 PDF 文档
  • 文档页面
  • Drawing
  • Interactive Features
  • Document Info and Metadata
  • Zend_Pdf module usage example


Document Info and Metadata - Zend Framework Manual

Interactive Features
Zend_Pdf
Zend Framework手册 中文版
Zend_Pdf module usage example

Document Info and Metadata

A PDF document may include general information such as the document's title, author, and creation and modification dates.

Historically this information is stored using special Info structure. This structure is available for read and writing as an associative array using properties public property of Zend_Pdf objects:

  1. $pdf = Zend_Pdf::load($pdfPath);
  2.
  3. echo $pdf->properties['Title'] . "\n";
  4. echo $pdf->properties['Author'] . "\n";
  5.
  6. $pdf->properties['Title'] = 'New Title.';
  7. $pdf->save($pdfPath);

The following keys are defined by PDF v1.4 (Acrobat 5) standard:

  • Title - string, optional, the document's title.

  • Author - string, optional, the name of the person who created the document.

  • Subject - string, optional, the subject of the document.

  • Keywords - string, optional, keywords associated with the document.

  • Creator - string, optional, if the document was converted to PDF from another format, the name of the application (for example, Adobe FrameMaker®) that created the original document from which it was converted.

  • Producer - string, optional, if the document was converted to PDF from another format, the name of the application (for example, Acrobat Distiller) that converted it to PDF..

  • CreationDate - string, optional, the date and time the document was created, in the following form: "D:YYYYMMDDHHmmSSOHH'mm'", where:

    • YYYY is the year.

    • MM is the month.

    • DD is the day (01–31).

    • HH is the hour (00–23).

    • mmis the minute (00–59).

    • SS is the second (00–59).

    • O is the relationship of local time to Universal Time (UT), denoted by one of the characters +, −, or Z (see below).

    • HH followed by ' is the absolute value of the offset from UT in hours (00–23).

    • mm followed by ' is the absolute value of the offset from UT in minutes (00–59).

    The apostrophe character (') after HH and mm is part of the syntax. All fields after the year are optional. (The prefix D:, although also optional, is strongly recommended.) The default values for MM and DD are both 01; all other numerical fields default to zero values. A plus sign (+) as the value of the O field signifies that local time is later than UT, a minus sign (−) that local time is earlier than UT, and the letter Z that local time is equal to UT. If no UT information is specified, the relationship of the specified time to UT is considered to be unknown. Whether or not the time zone is known, the rest of the date should be specified in local time.

    For example, December 23, 1998, at 7:52 PM, U.S. Pacific Standard Time, is represented by the string "D:199812231952−08'00'".

  • ModDate - string, optional, the date and time the document was most recently modified, in the same form as CreationDate.

  • Trapped - boolean, optional, indicates whether the document has been modified to include trapping information.

    • TRUE - The document has been fully trapped; no further trapping is needed.

    • FALSE - The document has not yet been trapped; any desired trapping must still be done.

    • NULL - Either it is unknown whether the document has been trapped or it has been partly but not yet fully trapped; some additional trapping may still be needed.

Since PDF v 1.6 metadata can be stored in the special XML document attached to the PDF (XMP - » Extensible Metadata Platform).

This XML document can be retrieved and attached to the PDF with Zend_Pdf::getMetadata() and Zend_Pdf::setMetadata($metadata) methods:

  1. $pdf = Zend_Pdf::load($pdfPath);
  2. $metadata = $pdf->getMetadata();
  3. $metadataDOM = new DOMDocument();
  4. $metadataDOM->loadXML($metadata);
  5.
  6. $xpath = new DOMXPath($metadataDOM);
  7. $pdfPreffixNamespaceURI = $xpath->query('/rdf:RDF/rdf:Description')
  8.                                 ->item(0)
  9.                                 ->lookupNamespaceURI('pdf');
  10. $xpath->registerNamespace('pdf', $pdfPreffixNamespaceURI);
  11.
  12. $titleNode = $xpath->query('/rdf:RDF/rdf:Description/pdf:Title')->item(0);
  13. $title = $titleNode->nodeValue;
  14. ...
  15.
  16. $titleNode->nodeValue = 'New title';
  17. $pdf->setMetadata($metadataDOM->saveXML());
  18. $pdf->save($pdfPath);

Common document properties are duplicated in the Info structure and Metadata document (if presented). It's user application responsibility now to keep them synchronized.

Interactive Features
Zend_Pdf
Zend Framework手册 中文版
Zend_Pdf module usage example
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Pdf
  • 简介
  • 生成和加载 PDF 文档
  • 保存修改到 PDF 文档
  • 文档页面
  • Drawing
  • Interactive Features
  • Document Info and Metadata
  • Zend_Pdf module usage example


Zend_Pdf module usage example - Zend Framework Manual

Document Info and Metadata
Zend_Pdf
Zend Framework手册 中文版
Zend_ProgressBar

Zend_Pdf module usage example

This section provides an example of module usage.

This example can be found in a demos/Zend/Pdf/demo.php file.

There are also test.pdf file, which can be used with this demo for test purposes.

Example #1 Zend_Pdf module usage demo

  1. /**
  2. * @package Zend_Pdf
  3. * @subpackage demo
  4. */
  5.
  6. if (!isset($argv[1])) {
  7.     echo "USAGE: php demo.php <pdf_file> [<output_pdf_file>]\n";
  8.     exit;
  9. }
  10.
  11. try {
  12.     $pdf = Zend_Pdf::load($argv[1]);
  13. } catch (Zend_Pdf_Exception $e) {
  14.     if ($e->getMessage() == 'Can not open \'' . $argv[1] .
  15.                             '\' file for reading.') {
  16.         // Create new PDF if file doesn't exist
  17.         $pdf = new Zend_Pdf();
  18.
  19.         if (!isset($argv[2])) {
  20.             // force complete file rewriting (instead of updating)
  21.             $argv[2] = $argv[1];
  22.         }
  23.     } else {
  24.         // Throw an exception if it's not the "Can't open file
  25.         // exception
  26.         throw $e;
  27.     }
  28. }
  29.
  30. //------------------------------------------------------------------------
  31. // Reverse page order
  32. $pdf->pages = array_reverse($pdf->pages);
  33.
  34. // Create new Style
  35. $style = new Zend_Pdf_Style();
  36. $style->setFillColor(new Zend_Pdf_Color_Rgb(0, 0, 0.9));
  37. $style->setLineColor(new Zend_Pdf_Color_GrayScale(0.2));
  38. $style->setLineWidth(3);
  39. $style->setLineDashingPattern(array(3, 2, 3, 4), 1.6);
  40. $fontH = Zend_Pdf_Font::fontWithName(Zend_Pdf_Font::FONT_HELVETICA_BOLD);
  41. $style->setFont($fontH, 32);
  42.
  43. try {
  44.     // Create new image object
  45.     $imageFile = dirname(__FILE__) . '/stamp.jpg';
  46.     $stampImage = Zend_Pdf_Image::imageWithPath($imageFile);
  47. } catch (Zend_Pdf_Exception $e) {
  48.     // Example of operating with image loading exceptions.
  49.     if ($e->getMessage() != 'Image extension is not installed.' &&
  50.         $e->getMessage() != 'JPG support is not configured properly.') {
  51.         throw $e;
  52.     }
  53.     $stampImage = null;
  54. }
  55.
  56. // Mark page as modified
  57. foreach ($pdf->pages as $page){
  58.     $page->saveGS()
  59.          ->setAlpha(0.25)
  60.          ->setStyle($style)
  61.          ->rotate(0, 0, M_PI_2/3);
  62.
  63.     $page->saveGS();
  64.     $page->clipCircle(550, -10, 50);
  65.     if ($stampImage != null) {
  66.         $page->drawImage($stampImage, 500, -60, 600, 40);
  67.     }
  68.     $page->restoreGS();
  69.
  70.     $page->drawText('Modified by Zend Framework!', 150, 0)
  71.          ->restoreGS();
  72. }
  73.
  74. // Add new page generated by Zend_Pdf object
  75. // (page is attached to the specified the document)
  76. $pdf->pages[] = ($page1 = $pdf->newPage('A4'));
  77.
  78. // Add new page generated by Zend_Pdf_Page object
  79. // (page is not attached to the document)
  80. $page2 = new Zend_Pdf_Page(Zend_Pdf_Page::SIZE_LETTER_LANDSCAPE);
  81. $pdf->pages[] = $page2;
  82.
  83. // Create new font
  84. $font = Zend_Pdf_Font::fontWithName(Zend_Pdf_Font::FONT_HELVETICA);
  85.
  86. // Apply font and draw text
  87. $page1->setFont($font, 36)
  88.       ->setFillColor(Zend_Pdf_Color_Html::color('#9999cc'))
  89.       ->drawText('Helvetica 36 text string', 60, 500);
  90.
  91. // Use font object for another page
  92. $page2->setFont($font, 24)
  93.       ->drawText('Helvetica 24 text string', 60, 500);
  94.
  95. // Use another font
  96. $fontT = Zend_Pdf_Font::fontWithName(Zend_Pdf_Font::FONT_TIMES);
  97. $page2->setFont($fontT, 32)
  98.       ->drawText('Times-Roman 32 text string', 60, 450);
  99.
  100. // Draw rectangle
  101. $page2->setFillColor(new Zend_Pdf_Color_GrayScale(0.8))
  102.       ->setLineColor(new Zend_Pdf_Color_GrayScale(0.2))
  103.       ->setLineDashingPattern(array(3, 2, 3, 4), 1.6)
  104.       ->drawRectangle(60, 400, 400, 350);
  105.
  106. // Draw circle
  107. $page2->setLineDashingPattern(Zend_Pdf_Page::LINE_DASHING_SOLID)
  108.       ->setFillColor(new Zend_Pdf_Color_Rgb(1, 0, 0))
  109.       ->drawCircle(85, 375, 25);
  110.
  111. // Draw sectors
  112. $page2->drawCircle(200, 375, 25, 2*M_PI/3, -M_PI/6)
  113.       ->setFillColor(new Zend_Pdf_Color_Cmyk(1, 0, 0, 0))
  114.       ->drawCircle(200, 375, 25, M_PI/6, 2*M_PI/3)
  115.       ->setFillColor(new Zend_Pdf_Color_Rgb(1, 1, 0))
  116.       ->drawCircle(200, 375, 25, -M_PI/6, M_PI/6);
  117.
  118. // Draw ellipse
  119. $page2->setFillColor(new Zend_Pdf_Color_Rgb(1, 0, 0))
  120.       ->drawEllipse(250, 400, 400, 350)
  121.       ->setFillColor(new Zend_Pdf_Color_Cmyk(1, 0, 0, 0))
  122.       ->drawEllipse(250, 400, 400, 350, M_PI/6, 2*M_PI/3)
  123.       ->setFillColor(new Zend_Pdf_Color_Rgb(1, 1, 0))
  124.       ->drawEllipse(250, 400, 400, 350, -M_PI/6, M_PI/6);
  125.
  126. // Draw and fill polygon
  127. $page2->setFillColor(new Zend_Pdf_Color_Rgb(1, 0, 1));
  128. $x = array();
  129. $y = array();
  130. for ($count = 0; $count < 8; $count++) {
  131.     $x[] = 140 + 25*cos(3*M_PI_4*$count);
  132.     $y[] = 375 + 25*sin(3*M_PI_4*$count);
  133. }
  134. $page2->drawPolygon($x, $y,
  135.                     Zend_Pdf_Page::SHAPE_DRAW_FILL_AND_STROKE,
  136.                     Zend_Pdf_Page::FILL_METHOD_EVEN_ODD);
  137.
  138. // ----------- Draw figures in modified coordination system --------------
  139.
  140. // Coordination system movement
  141. $page2->saveGS();
  142. $page2->translate(60, 250); // Shift coordination system
  143.
  144. // Draw rectangle
  145. $page2->setFillColor(new Zend_Pdf_Color_GrayScale(0.8))
  146.       ->setLineColor(new Zend_Pdf_Color_GrayScale(0.2))
  147.       ->setLineDashingPattern(array(3, 2, 3, 4), 1.6)
  148.       ->drawRectangle(0, 50, 340, 0);
  149.
  150. // Draw circle
  151. $page2->setLineDashingPattern(Zend_Pdf_Page::LINE_DASHING_SOLID)
  152.       ->setFillColor(new Zend_Pdf_Color_Rgb(1, 0, 0))
  153.       ->drawCircle(25, 25, 25);
  154.
  155. // Draw sectors
  156. $page2->drawCircle(140, 25, 25, 2*M_PI/3, -M_PI/6)
  157.       ->setFillColor(new Zend_Pdf_Color_Cmyk(1, 0, 0, 0))
  158.       ->drawCircle(140, 25, 25, M_PI/6, 2*M_PI/3)
  159.       ->setFillColor(new Zend_Pdf_Color_Rgb(1, 1, 0))
  160.       ->drawCircle(140, 25, 25, -M_PI/6, M_PI/6);
  161.
  162. // Draw ellipse
  163. $page2->setFillColor(new Zend_Pdf_Color_Rgb(1, 0, 0))
  164.       ->drawEllipse(190, 50, 340, 0)
  165.       ->setFillColor(new Zend_Pdf_Color_Cmyk(1, 0, 0, 0))
  166.       ->drawEllipse(190, 50, 340, 0, M_PI/6, 2*M_PI/3)
  167.       ->setFillColor(new Zend_Pdf_Color_Rgb(1, 1, 0))
  168.       ->drawEllipse(190, 50, 340, 0, -M_PI/6, M_PI/6);
  169.
  170. // Draw and fill polygon
  171. $page2->setFillColor(new Zend_Pdf_Color_Rgb(1, 0, 1));
  172. $x = array();
  173. $y = array();
  174. for ($count = 0; $count < 8; $count++) {
  175.     $x[] = 80 + 25*cos(3*M_PI_4*$count);
  176.     $y[] = 25 + 25*sin(3*M_PI_4*$count);
  177. }
  178. $page2->drawPolygon($x, $y,
  179.                     Zend_Pdf_Page::SHAPE_DRAW_FILL_AND_STROKE,
  180.                     Zend_Pdf_Page::FILL_METHOD_EVEN_ODD);
  181.
  182. // Draw line
  183. $page2->setLineWidth(0.5)
  184.       ->drawLine(0, 25, 340, 25);
  185.
  186. $page2->restoreGS();
  187.
  188. // Coordination system movement, skewing and scaling
  189. $page2->saveGS();
  190. $page2->translate(60, 150)     // Shift coordination system
  191.       ->skew(0, 0, 0, -M_PI/9) // Skew coordination system
  192.       ->scale(0.9, 0.9);       // Scale coordination system
  193.
  194. // Draw rectangle
  195. $page2->setFillColor(new Zend_Pdf_Color_GrayScale(0.8))
  196.       ->setLineColor(new Zend_Pdf_Color_GrayScale(0.2))
  197.       ->setLineDashingPattern(array(3, 2, 3, 4), 1.6)
  198.       ->drawRectangle(0, 50, 340, 0);
  199.
  200. // Draw circle
  201. $page2->setLineDashingPattern(Zend_Pdf_Page::LINE_DASHING_SOLID)
  202.       ->setFillColor(new Zend_Pdf_Color_Rgb(1, 0, 0))
  203.       ->drawCircle(25, 25, 25);
  204.
  205. // Draw sectors
  206. $page2->drawCircle(140, 25, 25, 2*M_PI/3, -M_PI/6)
  207.       ->setFillColor(new Zend_Pdf_Color_Cmyk(1, 0, 0, 0))
  208.       ->drawCircle(140, 25, 25, M_PI/6, 2*M_PI/3)
  209.       ->setFillColor(new Zend_Pdf_Color_Rgb(1, 1, 0))
  210.       ->drawCircle(140, 25, 25, -M_PI/6, M_PI/6);
  211.
  212. // Draw ellipse
  213. $page2->setFillColor(new Zend_Pdf_Color_Rgb(1, 0, 0))
  214.       ->drawEllipse(190, 50, 340, 0)
  215.       ->setFillColor(new Zend_Pdf_Color_Cmyk(1, 0, 0, 0))
  216.       ->drawEllipse(190, 50, 340, 0, M_PI/6, 2*M_PI/3)
  217.       ->setFillColor(new Zend_Pdf_Color_Rgb(1, 1, 0))
  218.       ->drawEllipse(190, 50, 340, 0, -M_PI/6, M_PI/6);
  219.
  220. // Draw and fill polygon
  221. $page2->setFillColor(new Zend_Pdf_Color_Rgb(1, 0, 1));
  222. $x = array();
  223. $y = array();
  224. for ($count = 0; $count < 8; $count++) {
  225.     $x[] = 80 + 25*cos(3*M_PI_4*$count);
  226.     $y[] = 25 + 25*sin(3*M_PI_4*$count);
  227. }
  228. $page2->drawPolygon($x, $y,
  229.                     Zend_Pdf_Page::SHAPE_DRAW_FILL_AND_STROKE,
  230.                     Zend_Pdf_Page::FILL_METHOD_EVEN_ODD);
  231.
  232. // Draw line
  233. $page2->setLineWidth(0.5)
  234.       ->drawLine(0, 25, 340, 25);
  235.
  236. $page2->restoreGS();
  237.
  238. //------------------------------------------------------------------------
  239.
  240. if (isset($argv[2])) {
  241.     $pdf->save($argv[2]);
  242. } else {
  243.     $pdf->save($argv[1], true /* update */);
  244. }
Document Info and Metadata
Zend_Pdf
Zend Framework手册 中文版
Zend_ProgressBar
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Pdf
  • 简介
  • 生成和加载 PDF 文档
  • 保存修改到 PDF 文档
  • 文档页面
  • Drawing
  • Interactive Features
  • Document Info and Metadata
  • Zend_Pdf module usage example


Zend_ProgressBar - Zend Framework Manual

Zend_Pdf module usage example
Zend Framework Reference
Zend Framework手册 中文版
Zend_ProgressBar

Zend_ProgressBar

Table of Contents
  • Zend_ProgressBar
Zend_Pdf module usage example
Zend Framework Reference
Zend Framework手册 中文版
Zend_ProgressBar
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


Zend_ProgressBar - Zend Framework Manual

Zend_ProgressBar
Zend_ProgressBar
Zend Framework手册 中文版
Zend_Queue

Zend_ProgressBar

Introduction

Zend_ProgressBar is a component to create and update progressbars in different environments. It consists of a single backend, which outputs the progress through one of the multiple adapters. On every update, it takes an absolute value and optionally a status message, and then calls the adapter with some precalculated values like percentage and estimated time left.

Basic Usage of Zend_Progressbar

Zend_ProgressBar is quite easy in its usage. You simply create a new instance of Zend_Progressbar, defining a min- and a max-value, and choose an adapter to output the data. If you want to process a file, you would do something like:

  1. $progressBar = new Zend_ProgressBar($adapter, 0, $fileSize);
  2.
  3. while (!feof($fp)) {
  4.     // Do something
  5.
  6.     $progressBar->update($currentByteCount);
  7. }
  8.
  9. $progressBar->finish();

In the first step, an instance of Zend_ProgressBar is created, with a specific adapter, a min-value of 0 and a max-value of the total filesize. Then a file is processed and in every loop the progressbar is updated with the current byte count. At the end of the loop, the progressbar status is set to finished.

You can also call the update() method of Zend_ProgressBar without arguments, which just recalculates ETA and notifies the adapter. This is useful when there is no data update but you want the progressbar to be updated.

Persistent progress

If you want the progressbar to be persistent over multiple requests, you can give the name of a session namespace as fourth argument to the constructor. In that case, the progressbar will not notify the adapter within the constructor, but only when you call update() or finish(). Also the current value, the status text and the start time for ETA calculation will be fetched in the next request run again.

Standard adapters

Zend_ProgressBar comes with the following three adapters:

  • Zend_ProgressBar_Adapter_Console

  • Zend_ProgressBar_Adapter_JsPush

  • Zend_ProgressBar_Adapter_JsPull

Zend_ProgressBar_Adapter_Console

Zend_ProgressBar_Adapter_Console is a text-based adapter for terminals. It can automatically detect terminal widths but supports custom widths as well. You can define which elements are displayed with the progressbar and as well customize the order of them. You can also define the style of the progressbar itself.

Note: Automatic console width recognition
 shell_exec is required for this feature to work on *nix based systems. On windows, there is always a fixed terminal width of 80 character, so no recognition is required there.

You can set the adapter options either via the set* methods or give an array or a Zend_Config instance with options as first parameter to the constructor. The available options are:

  • outputStream: A different output-stream, if you don't want to stream to STDOUT. Can be any other stream like php://stderr or a path to a file.

  • width: Either an integer or the AUTO constant of Zend_Console_ProgressBar.

  • elements: Either NULL for default or an array with at least one of the following constants of Zend_Console_ProgressBar as value:

    • ELEMENT_PERCENT: The current value in percent.

    • ELEMENT_BAR: The visual bar which display the percentage.

    • ELEMENT_ETA: The automatic calculated ETA. This element is firstly displayed after five seconds, because in this time, it is not able to calculate accurate results.

    • ELEMENT_TEXT: An optional status message about the current process.

  • textWidth: Width in characters of the ELEMENT_TEXT element. Default is 20.

  • charset: Charset of the ELEMENT_TEXT element. Default is utf-8.

  • barLeftChar: A string which is used left-hand of the indicator in the progressbar.

  • barRightChar: A string which is used right-hand of the indicator in the progressbar.

  • barIndicatorChar: A string which is used for the indicator in the progressbar. This one can be empty.

Zend_ProgressBar_Adapter_JsPush

Zend_ProgressBar_Adapter_JsPush is an adapter which let's you update a progressbar in a browser via Javascript Push. This means that no second connection is required to gather the status about a running process, but that the process itself sends its status directly to the browser.

You can set the adapter options either via the set* methods or give an array or a Zend_Config instance with options as first parameter to the constructor. The available options are:

  • updateMethodName: The javascript method which should be called on every update. Default value is Zend_ProgressBar_Update.

  • finishMethodName: The javascript method which should be called after finish status was set. Default value is NULL, which means nothing is done.

The usage of this adapter is quite simple. First you create a progressbar in your browser, either with JavaScript or previously created with plain HTML. Then you define the update method and optionally the finish method in JavaScript, both taking a json object as single argument. Then you call a webpage with the long-running process in a hidden iframe or object tag. While the process is running, the adapter will call the update method on every update with a json object, containing the following parameters:

  • current: The current absolute value

  • max: The max absolute value

  • percent: The calculated percentage

  • timeTaken: The time how long the process ran yet

  • timeRemaining: The expected time for the process to finish

  • text: The optional status message, if given

Example #1 Basic example for the client-side stuff

This example illustrates a basic setup of HTML, CSS and JavaScript for the JsPush adapter

  1. <div id="zend-progressbar-container">
  2.     <div id="zend-progressbar-done"></div>
  3. </div>
  4.
  5. <iframe src="long-running-process.php" id="long-running-process"></iframe>
  1. #long-running-process {
  2.     position: absolute;
  3.     left: -100px;
  4.     top: -100px;
  5.
  6.     width: 1px;
  7.     height: 1px;
  8. }
  9.
  10. #zend-progressbar-container {
  11.     width: 100px;
  12.     height: 30px;
  13.
  14.     border: 1px solid #000000;
  15.     background-color: #ffffff;
  16. }
  17.
  18. #zend-progressbar-done {
  19.     width: 0;
  20.     height: 30px;
  21.
  22.     background-color: #000000;
  23. }
  1. function Zend_ProgressBar_Update(data)
  2. {
  3.     document.getElementById('zend-progressbar-done').style.width = data.percent + '%';
  4. }

This will create a simple container with a black border and a block which indicates the current process. You should not hide the iframe or object by display: none;, as some browsers like Safari 2 will not load the actual content then.

Instead of creating your custom progressbar, you may want to use one of the available JavaScript libraries like Dojo, jQuery etc. For example, there are:

  • Dojo: http://dojotoolkit.org/book/dojo-book-0-9/part-2-dijit/user-assistance-and-feedback/progress-bar

  • jQuery: http://t.wits.sg/2008/06/20/jquery-progress-bar-11/

  • MooTools: http://davidwalsh.name/dw-content/progress-bar.php

  • Prototype: http://livepipe.net/control/progressbar

Note: Interval of updates
 You should take care of not sending too many updates, as every update has a min-size of 1kb. This is a requirement for the Safari browser to actually render and execute the function call. Internet Explorer has a similar limitation of 256 bytes.

Zend_ProgressBar_Adapter_JsPull

Zend_ProgressBar_Adapter_JsPull is the opposite of jsPush, as it requires to pull for new updates, instead of pushing updates out to the browsers. Generally you should use the adapter with the persistence option of the Zend_ProgressBar. On notify, the adapter sends a JSON string to the browser, which looks exactly like the JSON string which is send by the jsPush adapter. The only difference is, that it contains an additional parameter, finished, which is either FALSE when update() is called or TRUE, when finish() is called.

You can set the adapter options either via the set* methods or give an array or a Zend_Config instance with options as first parameter to the constructor. The available options are:

  • exitAfterSend: Exits the current request after the data were send to the browser. Default is TRUE.

Zend_ProgressBar
Zend_ProgressBar
Zend Framework手册 中文版
Zend_Queue
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_ProgressBar
  • Zend_ProgressBar


Zend_Queue - Zend Framework Manual

Zend_ProgressBar
Zend Framework Reference
Zend Framework手册 中文版
Introduction

Zend_Queue

Table of Contents
  • Introduction
  • Example usage
  • Framework
  • Adapters
  • Customizing Zend_Queue
  • Stomp
Zend_ProgressBar
Zend Framework Reference
Zend Framework手册 中文版
Introduction
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


Introduction - Zend Framework Manual

Zend_Queue
Zend_Queue
Zend Framework手册 中文版
Example usage

Introduction

Zend_Queue provides a factory function to create specific queue client objects.

A message queue is a method for distributed processing. For example, a Job Broker application may accept multiple applications for jobs from a variety of sources.

You could create a queue "/queue/applications" that would have a sender and a receiver. The sender would be any available source that could connect to your message service or indirectly to an application (web) that could connect to the message service.

The sender sends a message to the queue:

  1. <resume>
  2.     <name>John Smith</name>
  3.     <location>
  4.         <city>San Francisco</city>
  5.         <state>California</state>
  6.         <zip>00001</zip>
  7.     </location>
  8.     <skills>
  9.         <programming>PHP</programming>
  10.         <programming>Perl</programming>
  11.     </skills>
  12. </resume>

The recipient or consumer of the queue would pick up the message and process the resume.

There are many messaging patterns that can be applied to queues to abstract the flow of control from the code and provide metrics, transformations, and monitoring of messages queues. A good book on messaging patterns is » Enterprise Integration Patterns: Designing, Building, and Deploying Messaging Solutions (Addison-Wesley Signature Series) (ISBN-10 0321127420; ISBN-13 978-0321127426).

Zend_Queue
Zend_Queue
Zend Framework手册 中文版
Example usage
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Queue
  • Introduction
  • Example usage
  • Framework
  • Adapters
  • Customizing Zend_Queue
  • Stomp


Example usage - Zend Framework Manual

Introduction
Zend_Queue
Zend Framework手册 中文版
Framework

Example usage

The below example of Zend_Queue shows a variety of features, including queue creation, queue retrieval, message retrieval, message deletion, and sending messages.

  1. // For configuration options
  2. // @see Zend_Queue_Adapater::__construct()
  3. $options = array(
  4.     'name' => 'queue1',
  5. );
  6.
  7. // Create an array queue
  8. $queue = new Zend_Queue('Array', $options);
  9.
  10. // Get list of queues
  11. foreach ($queue->getQueues() as $name) {
  12.     echo $name, "\n";
  13. }
  14.
  15. // Create a new queue
  16. $queue2 = $queue->createQueue('queue2');
  17.
  18. // Get number of messages in a queue (supports Countable interface from SPL)
  19. echo count($queue);
  20.
  21. // Get up to 5 messages from a queue
  22. $messages = $queue->receive(5);
  23.
  24. foreach ($messages as $i => $message) {
  25.     echo $message->body, "\n";
  26.
  27.     // We have processed the message; now we remove it from the queue.
  28.     $queue->deleteMessage($message);
  29. }
  30.
  31. // Send a message to the currently active queue
  32. $queue->send('My Test Message');
  33.
  34. // Delete a queue we created and all of it's messages
  35. $queue->deleteQueue('queue2');
Introduction
Zend_Queue
Zend Framework手册 中文版
Framework
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Queue
  • Introduction
  • Example usage
  • Framework
  • Adapters
  • Customizing Zend_Queue
  • Stomp


Framework - Zend Framework Manual

Example usage
Zend_Queue
Zend Framework手册 中文版
Adapters

Framework

The Zend_Queue is a proxy that hides the details of the queue services. The queue services are represented by Zend_Queue_Adapter_<service>. For example, Zend_Queue_Adapter_Db is a queue that will use database tables to store and retrieve messages.

Below is an example for using database tables for a queuing system:

  1. $options = array(
  2.     'name'          => 'queue1',
  3.     'driverOptions' => array(
  4.         'host'      => '127.0.0.1',
  5.         'port'      => '3306',
  6.         'username'  => 'queue',
  7.         'password'  => 'queue',
  8.         'dbname'    => 'queue',
  9.         'type'      => 'pdo_mysql'
  10.     )
  11. );
  12.
  13. // Create a database queue.
  14. // Zend_Queue will prepend Zend_Queue_Adapter_ to 'Db' for the class name.
  15. $queue = new Zend_Queue('Db', $options);

The Zend_Queue constructor will create a Zend_Queue_Adapter_Db and initialize the adapter with the configuration settings.

The accepted configuration settings for each adapter are provided in the adapter notes.

Zend_Queue returns messages using the class Zend_Queue_Message_Iterator, which is an implementation of SPL Iterator and Countable. Zend_Queue_Message_Iterator contains an array of Zend_Queue_Message objects.

  1. $messages = $queue->receive(5);
  2. foreach ($messages as $i => $message) {
  3.     echo "$i) Message => ", $message->body, "\n";
  4. }

Any exceptions thrown are of class Zend_Queue_Exception.

Introduction

Zend_Queue is a proxy class that represents an adapter.

The send(), count($queue), and receive() methods are employed by each adapter to interact with queues.

The createQueue(), deleteQueue() methods are used to manage queues.

Commonality among adapters

The queue services supported by Zend_Queue do not all support the same functions. For example, Zend_Queue_Adapter_Array, Zend_Queue_Adapter_Db, support all functions, while Zend_Queue_Adapter_Activemq does not support queue listing, queue deletion, or counting of messages.

You can determine what functions are supported by using Zend_Queue::isSupported() or Zend_Queue::getCapabilities().

  • create() - create a queue

  • delete() - delete a queue

  • send() - send a message

    send() is not available in all adapters; the Zend_Queue_Adapter_Null does not support send().

  • receive() - receive messages

    receive() is not available in all adapters; the Zend_Queue_Adapter_Null does not support receive().

  • deleteMessage() - delete a message

  • count() - count the number of messages in a queue

  • isExists() - checks the existence of a queue

receive() methods are employed by each adapter to interact with queues.

The createQueue() and deleteQueue() methods are used to manage queues.

Example usage
Zend_Queue
Zend Framework手册 中文版
Adapters
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Queue
  • Introduction
  • Example usage
  • Framework
  • Adapters
  • Customizing Zend_Queue
  • Stomp


Adapters - Zend Framework Manual

Framework
Zend_Queue
Zend Framework手册 中文版
Customizing Zend_Queue

Adapters

Zend_Queue supports all queues implementing the interface Zend_Queue_Adapter_AdapterInterface. The following Message Queue services are supported:

  • » Apache ActiveMQ.

  • A database driven queue via Zend_Db.

  • A » MemcacheQ queue driven via Memcache.

  • » Zend Platform's Job Queue.

  • A local array. Useful for unit testing.

Note: Limitations
 Message transaction handling is not supported.

Specific Adapters - Configuration settings

If a default setting is indicated then the parameter is optional. If a default setting is not specified then the parameter is required.

Apache ActiveMQ - Zend_Queue_Adapter_Activemq

Options listed here are known requirements. Not all messaging servers require username or password.

  • $options['name'] = '/temp/queue1';

    This is the name of the queue that you wish to start using. (Required)

  • $options['driverOptions']['host'] = 'host.domain.tld';

    $options['driverOptions']['host'] = '127.0.0.1';

    You may set host to an IP address or a hostname.

    Default setting for host is '127.0.0.1'.

  • $options['driverOptions']['port'] = 61613;

    Default setting for port is 61613.

  • $options['driverOptions']['username'] = 'username';

    Optional for some messaging servers. Read the manual for your messaging server.

  • $options['driverOptions']['password'] = 'password';

    Optional for some messaging servers. Read the manual for your messaging server.

  • $options['driverOptions']['timeout_sec'] = 2;

    $options['driverOptions']['timeout_usec'] = 0;

    This is the amount of time that Zend_Queue_Adapter_Activemq will wait for read activity on a socket before returning no messages.

Db - Zend_Queue_Adapter_Db

Driver options are checked for a few required options such as type, host, username, password, and dbname. You may pass along additional parameters for Zend_DB::factory() as parameters in $options['driverOptions']. An example of an additional option not listed here, but could be passed would be port.

  1. $options = array(
  2.     'driverOptions' => array(
  3.         'host'      => 'db1.domain.tld',
  4.         'username'  => 'my_username',
  5.         'password'  => 'my_password',
  6.         'dbname'    => 'messaging',
  7.         'type'      => 'pdo_mysql',
  8.         'port'      => 3306, // optional parameter.
  9.     ),
  10.     'options' => array(
  11.         // use Zend_Db_Select for update, not all databases can support this
  12.         // feature.
  13.         Zend_Db_Select::FOR_UPDATE => true
  14.     )
  15. );
  16.
  17. // Create a database queue.
  18. $queue = new Zend_Queue('Db', $options);

  • $options['name'] = 'queue1';

    This is the name of the queue that you wish to start using. (Required)

  • $options['driverOptions']['type'] = 'Pdo';

    type is the adapter you wish to have Zend_Db::factory() use. This is the first parameter for the Zend_Db::factory() class method call.

  • $options['driverOptions']['host'] = 'host.domain.tld';

    $options['driverOptions']['host'] = '127.0.0.1';

    You may set host to an IP address or a hostname.

    Default setting for host is '127.0.0.1'.

  • $options['driverOptions']['username'] = 'username';

  • $options['driverOptions']['password'] = 'password';

  • $options['driverOptions']['dbname'] = 'dbname';

    The database name that you have created the required tables for. See the notes section below.

MemcacheQ - Zend_Queue_Adapter_Memcacheq

  • $options['name'] = 'queue1';

    This is the name of the queue that you wish to start using. (Required)

  • $options['driverOptions']['host'] = 'host.domain.tld';

    $options['driverOptions']['host'] = '127.0.0.1;'

    You may set host to an IP address or a hostname.

    Default setting for host is '127.0.0.1'.

  • $options['driverOptions']['port'] = 22201;

    The default setting for port is 22201.

Zend Platform Job Queue - Zend_Queue_Adapter_PlatformJobQueue

  • $options['daemonOptions']['host'] = '127.0.0.1:10003';

    The hostname and port corresponding to the Zend Platform Job Queue daemon you will use. (Required)

  • $options['daemonOptions']['password'] = '1234';

    The password required for accessing the Zend Platform Job Queue daemon. (Required)

Array - Zend_Queue_Adapter_Array

  • $options['name'] = 'queue1';

    This is the name of the queue that you wish to start using. (Required)

Notes for Specific Adapters

The following adapters have notes:

Apache ActiveMQ

Visibility duration for Zend_Queue_Adapter_Activemq is not available.

While Apache's ActiveMQ will support multiple subscriptions, the Zend_Queue does not. You must create a new Zend_Queue object for each individual subscription.

ActiveMQ queue/topic names must begin with one of:

  • /queue/

  • /topic/

  • /temp-queue/

  • /temp-topic/

For example: /queue/testing

The following functions are not supported:

  • create() - create queue. Calling this function will throw an exception.

  • delete() - delete queue. Calling this function will throw an exception.

  • getQueues() - list queues. Calling this function will throw an exception.

Zend_Db

The database CREATE TABLE ( ... ) SQL statement can be found in Zend/Queue/Adapter/Db/queue.sql.

MemcacheQ

Memcache can be downloaded from » http://www.danga.com/memcached/.

MemcacheQ can be downloaded from » http://memcachedb.org/memcacheq/.

  • deleteMessage() - Messages are deleted upon reception from the queue. Calling this function would have no effect. Calling this function will throw an error.

  • count() or count($adapter) - MemcacheQ does not support a method for counting the number of items in a queue. Calling this function will throw an error.

Zend Platform Job Queue

Job Queue is a feature of Zend Platform's Enterprise Solution offering. It is not a traditional message queue, and instead allows you to queue a script to execute, along with the parameters you wish to pass to it. You can find out more about Job Queue » on the zend.com website.

The following is a list of methods where this adapter's behavior diverges from the standard offerings:

  • create() - Zend Platform does not have the concept of discrete queues; instead, it allows administrators to provide scripts for processing jobs. Since adding new scripts is restricted to the administration interface, this method simply throws an exception indicating the action is forbidden.

  • isExists() - Just like create(), since Job Queue does not have a notion of named queues, this method throws an exception when invoked.

  • delete() - similar to create(), deletion of JQ scripts is not possible except via the admin interface; this method raises an exception.

  • getQueues() - Zend Platform does not allow introspection into the attached job handling scripts via the API. This method throws an exception.

  • count() - returns the total number of jobs currently active in the Job Queue.

  • send() - this method is perhaps the one method that diverges most from other adapters. The $message argument may be one of three possible types, and will operate differently based on the value passed:

    • string - the name of a script registered with Job Queue to invoke. If passed in this way, no arguments are provided to the script.

    • array - an array of values with which to configure a ZendApi_Job object. These may include the following:

      • script - the name of the Job Queue script to invoke. (Required)

      • priority - the job priority to use when registering with the queue.

      • name - a short string describing the job.

      • predecessor - the ID of a job on which this one depends, and which must be executed before this one may begin.

      • preserved - whether or not to retain the job within the Job Queue history. By default, off; pass a TRUE value to retain it.

      • user_variables - an associative array of all variables you wish to have in scope during job execution (similar to named arguments).

      • interval - how often, in seconds, the job should run. By default, this is set to 0, indicating it should run once, and once only.

      • end_time - an expiry time, past which the job should not run. If the job was set to run only once, and end_time has passed, then the job will not be executed. If the job was set to run on an interval, it will not execute again once end_time has passed.

      • schedule_time - a UNIX timestamp indicating when to run the job; by default, 0, indicating the job should run as soon as possible.

      • application_id - the application identifier of the job. By default, this is NULL, indicating that one will be automatically assigned by the queue, if the queue was assigned an application ID.

      As noted, only the script argument is required; all others are simply available to allow passing more fine-grained detail on how and when to run the job.

    • ZendApi_Job - finally, you may simply pass a ZendApi_Job instance, and it will be passed along to Platform's Job Queue.

    In all instances, send() returns a Zend_Queue_Message_PlatformJob object, which provides access to the ZendApi_Job object used to communicate with Job Queue.

  • receive() - retrieves a list of active jobs from Job Queue. Each job in the returned set will be an instance of Zend_Queue_Message_PlatformJob.

  • deleteMessage() - since this adapter only works with Job Queue, this method expects the provided $message to be a Zend_Queue_Message_PlatformJob instance, and will throw an exception otherwise.

Array (local)

The Array queue is a PHP array() in local memory. The Zend_Queue_Adapter_Array is good for unit testing.

Framework
Zend_Queue
Zend Framework手册 中文版
Customizing Zend_Queue
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Queue
  • Introduction
  • Example usage
  • Framework
  • Adapters
  • Customizing Zend_Queue
  • Stomp


Customizing Zend_Queue - Zend Framework Manual

Adapters
Zend_Queue
Zend Framework手册 中文版
Stomp

Customizing Zend_Queue

Creating your own adapter

Zend_Queue will accept any adapter that implements Zend_Queue_Adapter_AdapterAbstract. You can create your own adapter by extending one of the existing adapters, or the abstract class Zend_Queue_Adapter_AdapterAbstract. I suggest reviewing Zend_Queue_Adapter_Array as this adapter is the easiest to conceptualize.

  1. class Custom_DbForUpdate extends Zend_Queue_Adapter_Db
  2. {
  3.     /**
  4.      * @see code in tests/Zend/Queue/Custom/DbForUpdate.php
  5.      *
  6.      * Custom_DbForUpdate uses the SELECT ... FOR UPDATE to find it's rows.
  7.      * this is more likely to produce the wanted rows than the existing code.
  8.      *
  9.      * However, not all databases have SELECT ... FOR UPDATE as a feature.
  10.      *
  11.      * Note: this was later converted to be an option for Zend_Queue_Adapter_Db
  12.      *
  13.      * This code still serves as a good example.
  14.      */
  15. }
  16.
  17. $options = array(
  18.     'name'          => 'queue1',
  19.     'driverOptions' => array(
  20.         'host'      => '127.0.0.1',
  21.         'port'      => '3306',
  22.         'username'  => 'queue',
  23.         'password'  => 'queue',
  24.         'dbname'    => 'queue',
  25.         'type'      => 'pdo_mysql'
  26.     )
  27. );
  28.
  29. $adapter = new Custom_DbForUpdate($options);
  30. $queue = new Zend_Queue($adapter, $options);

You can also change the adapter on the fly as well.

  1. $adapter = new MyCustom_Adapter($options);
  2. $queue   = new Zend_Queue($options);
  3. $queue->setAdapter($adapter);
  4. echo "Adapter: ", get_class($queue->getAdapter()), "\n";

or

  1. $options = array(
  2.     'name'           => 'queue1',
  3.     'namespace'      => 'Custom',
  4.     'driverOptions'  => array(
  5.         'host'       => '127.0.0.1',
  6.         'port'       => '3306',
  7.         'username'   => 'queue',
  8.         'password'   => 'queue',
  9.         'dbname'     => 'queue',
  10.         'type'       => 'pdo_mysql'
  11.     )
  12. );
  13. $queue = new Zend_Queue('DbForUpdate', $config); // loads Custom_DbForUpdate

Creating your own message class

Zend_Queue will also accept your own message class. Our variables start with an underscore. For example:

  1. class Zend_Queue_Message
  2. {
  3.     protected $_data = array();
  4. }

You can extend the existing messaging class. See the example code in tests/Zend/Queue/Custom/Message.php.

Creating your own message iterator class

Zend_Queue will also accept your own message iterator class. The message iterator class is used to return messages from Zend_Queue_Adapter_Abstract::recieve(). Zend_Queue_Abstract::receive() should always return a container class like Zend_Queue_Message_Iterator, even if there is only one message.

See the example filename in tests/Zend/Queue/Custom/Messages.php.

Creating your own queue class

Zend_Queue can also be overloaded easily.

See the example filename in tests/Zend/Queue/Custom/Queue.php.

Adapters
Zend_Queue
Zend Framework手册 中文版
Stomp
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Queue
  • Introduction
  • Example usage
  • Framework
  • Adapters
  • Customizing Zend_Queue
  • Stomp


Stomp - Zend Framework Manual

Customizing Zend_Queue
Zend_Queue
Zend Framework手册 中文版
Zend_Reflection

Stomp

Zend_Queue_Stomp provides a basic client to communicate with » Stomp compatible servers. Some servers, such as Apache ActiveMQ and RabbitMQ, will allow you to communicate by other methods, such as HTTP, and XMPP.

The Stomp protocol provides » StompConnect which supports any » Java Message Service (JMS) provider. Stomp is supported by » Apache ActiveMQ, » RabbitMQ, » stompserver, and » Gozirra.

Stomp - Supporting classes

  • Zend_Queue_Stomp_Frame. This class provides the basic functions for manipulating a Stomp Frame.

  • Zend_Queue_Stomp_Client. This class provides the basic functions to send() and receive() Zend_Queue_Stomp_Frames to and from a Stomp compatible server.

Customizing Zend_Queue
Zend_Queue
Zend Framework手册 中文版
Zend_Reflection
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Queue
  • Introduction
  • Example usage
  • Framework
  • Adapters
  • Customizing Zend_Queue
  • Stomp


Zend_Reflection - Zend Framework Manual

Stomp
Zend Framework Reference
Zend Framework手册 中文版
Introduction

Zend_Reflection

Table of Contents
  • Introduction
  • Zend_Reflection Examples
  • Zend_Reflection Reference
Stomp
Zend Framework Reference
Zend Framework手册 中文版
Introduction
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


Introduction - Zend Framework Manual

Zend_Reflection
Zend_Reflection
Zend Framework手册 中文版
Zend_Reflection Examples

Introduction

Zend_Reflection is a drop-in extension to PHP's own » Reflection API, providing several additional features:

  • Ability to retrieve return values types.

  • Ability to retrieve method and function parameter types.

  • Ability to retrieve class property types.

  • DocBlocks gain a Reflection class, allowing introspection of docblocks. This provides the ability to determine what annotation tags have been defined as well as to retrieve their values, and the ability to retrieve the short and long descriptions.

  • Files gain a Reflection class, allowing introspection of PHP files. This provides the ability to determine what functions and classes are defined in a given file, as well as to introspect them.

  • Ability to override any Reflection class with your own variant, for the entire reflection tree you create.

In general, Zend_Reflection works just like the standard Reflection API, but provides a few additional methods for retrieving artifacts not defined in the Reflection API.

Zend_Reflection
Zend_Reflection
Zend Framework手册 中文版
Zend_Reflection Examples
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Reflection
  • Introduction
  • Zend_Reflection Examples
  • Zend_Reflection Reference


Zend_Reflection Examples - Zend Framework Manual

Introduction
Zend_Reflection
Zend Framework手册 中文版
Zend_Reflection Reference

Zend_Reflection Examples

Example #1 Performing reflection on a file

  1. $r = new Zend_Reflection_File($filename);
  2. printf(
  3.     "===> The %s file\n".
  4.     "     has %d lines\n",
  5.     $r->getFileName(),
  6.     $r->getEndLine()
  7. );
  8.
  9. $classes = $r->getClasses();
  10. echo "     It has " . count($classes) . ":\n";
  11. foreach ($classes as $class) {
  12.     echo "         " . $class->getName() . "\n";
  13. }
  14.
  15. $functions = $r->getFunctions();
  16. echo "     It has " . count($functions) . ":\n";
  17. foreach ($functions as $function) {
  18.     echo "         " . $function->getName() . "\n";
  19. }

Example #2 Performing reflection on a class

  1. $r = new Zend_Reflection_Class($class);
  2.
  3. printf(
  4.     "The class level docblock has the short description: %s\n".
  5.     "The class level docblock has the long description:\n%s\n",
  6.     $r->getDocblock()->getShortDescription(),
  7.     $r->getDocblock()->getLongDescription(),
  8. );
  9.
  10. // Get the declaring file reflection
  11. $file = $r->getDeclaringFile();

Example #3 Performing reflection on a method

  1. $r = new Zend_Reflection_Method($class, $name);
  2.
  3. printf(
  4. "The method '%s' has a return type of %s",
  5.     $r->getName(),
  6.     $r->getReturn()
  7. );
  8.
  9. foreach ($r->getParameters() as $key => $param) {
  10.     printf(
  11.         "Param at position '%d' is of type '%s'\n",
  12.         $key,
  13.         $param->getType()
  14.     );
  15. }

Example #4 Performing reflection on a docblock

  1. $r = new Zend_Reflection_Method($class, $name);
  2. $docblock = $r->getDocblock();
  3.
  4. printf(
  5.     "The short description: %s\n".
  6.     "The long description:\n%s\n",
  7.     $r->getDocblock()->getShortDescription(),
  8.     $r->getDocblock()->getLongDescription(),
  9. );
  10.
  11. foreach ($docblock->getTags() as $tag) {
  12.     printf(
  13.         "Annotation tag '%s' has the description '%s'\n",
  14.         $tag->getName(),
  15.         $tag->getDescription()
  16.     );
  17. }
Introduction
Zend_Reflection
Zend Framework手册 中文版
Zend_Reflection Reference
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Reflection
  • Introduction
  • Zend_Reflection Examples
  • Zend_Reflection Reference


Zend_Reflection Reference - Zend Framework Manual

Zend_Reflection Examples
Zend_Reflection
Zend Framework手册 中文版
Zend_Registry

Zend_Reflection Reference

The various classes in Zend_Reflection mimic the API of PHP's » Reflection API - with one important difference. PHP's Reflection API does not provide introspection into docblock annotation tags, nor into parameter variable types or return types.

Zend_Reflection analyzes method docblock annotations to determine parameter variable types and the return type. Specifically, the @param and @return annotations are used. However, you can also check for any other annotation tags, as well as the standard "short" and "long" descriptions.

Each reflection object in Zend_Reflection overrides the getDocblock() method to return an instance of Zend_Reflection_Docblock. This class provides introspection into the docblocks and annotation tags.

Zend_Reflection_File is a new reflection class that allows introspection of PHP files. With it, you can retrieve the classes, functions, and global PHP code contained in the file.

Finally, the various methods that return other reflection objects allow a second parameter, the name of the reflection class to use for the returned reflection object.

Zend_Reflection_Docblock

Zend_Reflection_Docblock is the heart of Zend_Reflection's value-add over PHP's Reflection API. It provides the following methods:

  • getContents(): returns the full contents of the docblock.

  • getStartLine(): returns the starting position of the docblock within the defining file.

  • getEndLine(): get last line of docblock within the defining file.

  • getShortDescription(): get the short, one-line description (usually the first line of the docblock).

  • getLongDescription(): get the long description from the docblock.

  • hasTag($name): determine if the docblock has the given annotation tag.

  • getTag($name): Retrieve the given annotation tag reflection object, or a boolean FALSE if it's not present.

  • getTags($filter): Retrieve all tags, or all tags matching the given $filter string. The tags returned will be an array of Zend_Reflection_Docblock_Tag objects.

Zend_Reflection_Docblock_Tag

Zend_Reflection_Docblock_Tag provides reflection for individual annotation tags. Most tags consist of only a name and a description. In the case of some special tags, the class provides a factory method for retrieving an instance of the appropriate class.

The following methods are defined for Zend_Reflection_Docblock_Tag:

  • factory($tagDocblockLine): instantiate the appropriate tag reflection class and return it.

  • getName(): return the annotation tag name.

  • getDescription(): return the annotation description.

Zend_Reflection_Docblock_Tag_Param

Zend_Reflection_Docblock_Tag_Param is a specialized version of Zend_Reflection_Docblock_Tag. The @param annotation tag description consists of the parameter type, variable name, and variable description. It adds the following methods to Zend_Reflection_Docblock_Tag:

  • getType(): return the parameter variable type.

  • getVariableName(): return the parameter variable name.

Zend_Reflection_Docblock_Tag_Return

Like Zend_Reflection_Docblock_Tag_Param, Zend_Reflection_Docblock_Tag_Return is a specialized version of Zend_Reflection_Docblock_Tag. The @return annotation tag description consists of the return type and variable description. It adds the following method to Zend_Reflection_Docblock_Tag:

  • getType(): return the return type.

Zend_Reflection_File

Zend_Reflection_File provides introspection into PHP files. With it, you can introspect the classes, functions, and bare PHP code defined in a file. It defines the following methods:

  • getFileName(): retrieve the filename of the file being reflected.

  • getStartLine(): retrieve the starting line of the file (always "1").

  • getEndLine() retrieve the last line / number of lines in the file.

  • getDocComment($reflectionClass = 'Zend_Reflection_Docblock'): retrive the file-level docblock reflection object.

  • getClasses($reflectionClass = 'Zend_Reflection_Class'): retrieve an array of reflection objects, one for each class defined in the file.

  • getFunctions($reflectionClass = 'Zend_Reflection_Function'): retrieve an array of reflection objects, one for each function defined in the file.

  • getClass($name = null, $reflectionClass = 'Zend_Reflection_Class'): retrieve the reflection object for a single class.

  • getContents(): retrieve the full contents of the file.

Zend_Reflection_Class

Zend_Reflection_Class extends ReflectionClass, and follows its API. It adds one additional method, getDeclaringFile(), which may be used to retrieve the Zend_Reflection_File reflection object for the defining file.

Additionally, the following methods add an additional argument for specifying the reflection class to use when fetching a reflection object:

  • getDeclaringFile($reflectionClass = 'Zend_Reflection_File')

  • getDocblock($reflectionClass = 'Zend_Reflection_Docblock')

  • getInterfaces($reflectionClass = 'Zend_Reflection_Class')

  • getMethod($reflectionClass = 'Zend_Reflection_Method')

  • getMethods($filter = -1, $reflectionClass = 'Zend_Reflection_Method')

  • getParentClass($reflectionClass = 'Zend_Reflection_Class')

  • getProperty($name, $reflectionClass = 'Zend_Reflection_Property')

  • getProperties($filter = -1, $reflectionClass = 'Zend_Reflection_Property')

Zend_Reflection_Extension

Zend_Reflection_Extension extends ReflectionExtension, and follows its API. It overrides the following methods to add an additional argument for specifying the reflection class to use when fetching a reflection object:

  • getFunctions($reflectionClass = 'Zend_Reflection_Function'): retrieve an array of reflection objects representing the functions defined by the extension.

  • getClasses($reflectionClass = 'Zend_Reflection_Class'): retrieve an array of reflection objects representing the classes defined by the extension.

Zend_Reflection_Function

Zend_Reflection_Function adds a method for retrieving the function return type, as well as overrides several methods to allow specifying the reflection class to use for returned reflection objects.

  • getDocblock($reflectionClass = 'Zend_Reflection_Docblock'): retrieve the function docblock reflection object.

  • getParameters($reflectionClass = 'Zend_Reflection_Parameter'): retrieve an array of all function parameter reflection objects.

  • getReturn(): retrieve the return type reflection object.

Zend_Reflection_Method

Zend_Reflection_Method mirrors Zend_Reflection_Function, and only overrides one additional method:

  • getParentClass($reflectionClass = 'Zend_Reflection_Class'): retrieve the parent class reflection object.

Zend_Reflection_Parameter

Zend_Reflection_Parameter adds a method for retrieving the parameter type, as well as overrides methods to allow specifying the reflection class to use on returned reflection objects.

  • getDeclaringClass($reflectionClass = 'Zend_Reflection_Class'): get the declaring class of the parameter as a reflection object (if available).

  • getClass($reflectionClass = 'Zend_Reflection_Class'): get the class of the parameter as a reflection object (if available).

  • getDeclaringFunction($reflectionClass = 'Zend_Reflection_Function'): get the function of the parameter as a reflection object (if available).

  • getType(): get the parameter type.

Zend_Reflection_Property

Zend_Reflection_Property overrides a single method in order to allow specifying the returned reflection object class:

  • getDeclaringClass($reflectionClass = 'Zend_Reflection_Class'): retrieve the declaring class of the property as a reflection object.

Zend_Reflection Examples
Zend_Reflection
Zend Framework手册 中文版
Zend_Registry
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Reflection
  • Introduction
  • Zend_Reflection Examples
  • Zend_Reflection Reference


Zend_Registry - Zend Framework Manual

Zend_Reflection Reference
Zend Framework Reference
Zend Framework手册 中文版
使用对象注册表（Registry）

Zend_Registry

Table of Contents
  • 使用对象注册表（Registry）
Zend_Reflection Reference
Zend Framework Reference
Zend Framework手册 中文版
使用对象注册表（Registry）
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


使用对象注册表（Registry） - Zend Framework Manual

Zend_Registry
Zend_Registry
Zend Framework手册 中文版
Zend_Rest

使用对象注册表（Registry）

对象注册表（或称对象仓库）是一个用于在整个应用空间（application space）内存储对象和值的容器。通过把对象存储在其中，我们可以在整个项目的任何地方使用同一个对象。这种机制相当于一种全局存储。

我们可以通过Zend_Registry类的静态方法来使用对象注册表，另外，由于该类是一个数组对象，你可以使用数组形式来访问其中的类方法。

设置Registry中的值

要保存一项内容到注册表中，我们可以使用静态方法 set()。

Example #1 set() 使用示例：

Zend_Registry::set('index', $value);

$value可以是一个对象、数组或者标量。你可以再次使用set()来为注册表中已有的值设置一个新值。

index参数可以是一个标量，即字符串或整数，就像使用数组一样，类似于数组的索引/键名。

获取Registry中的值

可以使用 get()方法来获取Registry中某项内容的值。

Example #2 get() 方法示例：

$value = Zend_Registry::get('index');

getInstance()返回静态registry对象。

registry对象是可迭代的（iterable）。

Example #3 迭代一个registry对象：

$registry = Zend_Registry::getInstance();

foreach ($registry as $index => $value) {
    echo "Registry index $index contains:\n";
    var_dump($value);
}

创建一个Registry对象

除了可以使用静态方法来访问Registry对象之外，你可以直接实例化它，就像使用普通的对象一样。

如果通过静态方法来访问registry对象的实例，它很方便进行静态存储，你可以在程序中的任何地方访问它。

如果使用传统的new 方法来创建registry的实例，则你可以使用数组一样的方式来初始化registry中的内容。

Example #4 创建一个registry对象

$registry = new Zend_Registry(array('index' => $value));

在创建这个对象实例之后，你可以使用数组对象方法来使用它，或者你可以把这个对象实例通过静态方法setInstance()设置为静态对象实例。

Example #5 Example of initializing the static registry

$registry = new Zend_Registry(array('index' => $value));

Zend_Registry::setInstance($registry);

如果静态的注册表对象已经被初始化过，则setInstance()方法会抛出一个Zend_Exception异常。

像访问数组一样访问Registry对象

如果你要一次访问或设置多个值，你会发现使用数组方式是很方便的。

Example #6 array 方式访问示例：

$registry = Zend_Registry::getInstance();

$registry['index'] = $value;

var_dump( $registry['index'] );

对象方式访问Registry

你会发现使用面向对象风格来访问registry对象也是方便的，对象中的属性名称作为索引。 要这样做，你需要使用ArrayObject::ARRAY_AS_PROPS选项来创建registry对象，并初始化静态实例。你要在静态的registry被第一次访问之前就完成这个工作。小心使用这个选项，因为某些版本的PHP在使用这个选项时会有bug。

Example #7 对象形式的访问：

//在你的bootstrap代码中：
$registry = new Zend_Registry(array(), ArrayObject::ARRAY_AS_PROPS)
Zend_Registry::setInstance($registry);
$registry->tree = 'apple';

.
.
.

//在程序的任何其它地方：
$registry = Zend_Registry::getInstance();

echo $registry->tree; // echo's "apple"

$registry->index = $value;

var_dump($registry->index);

查询一个索引是否存在

可以使用静态方法isRegistered()来查询是否某个特定的索引已经设置了相应的值。

Example #8 isRegistered() 示例：

if (Zend_Registry::isRegistered($index)) {
    $value = Zend_Registry::get($index);
}

要确定一个数组对象中的某个特定索引的值是否设定，可以使用isset()函数，就像在普通的数组中那样使用。

Example #9 isset() 示例：

$registry = Zend_Registry::getInstance();

// using array-access syntax
if (isset($registry['index'])) {
    var_dump( $registry['index'] );
}

// using object-access syntax, if enabled
if (isset($registry->index)) {
    var_dump( $registry->index );
}

扩展Registry对象

静态registry对象是类Zend_Registry的一个实例。如果你想给它增加功能，你可以继承Zend_Registry类，然后指定使用这个类来访问对象注册表。你可以使用静态方法setClassName()来指定使用这个类。注意这个类一定要是Zend_Registry的子类。

Example #10 指定静态注册表的类名：

Zend_Registry::setClassName('My_Registry');

Zend_Registry::set('index', $value);

如果你在registry已经被访问过后尝试设定该类名，则registry抛出一个异常。建议你在boostrap代码(即index.php)中设置该类名。

删除静态注册表

尽管这不是必需的，你可以使用_unsetInstance()方法来删除registry的静态实例。

Note: 数据丢失的风险
 在使用_unsetInstance()的时候，静态注册表中的所有数据都会丢失并且无法恢复。

有时你可能需要_unsetInstance()这个方法。例如你想在已经初始化过registry对象之后，再使用setInstance()或 setClassName()，那么你可以使用_unsetInstance()先把静态实例删除了，然后才能使用那些方法。

Example #11 _unsetInstance() 示例：

Zend_Registry::set('index', $value);

Zend_Registry::_unsetInstance();

// 改变我们要使用的类
Zend_Registry::setClassName('My_Registry');

Zend_Registry::set('index', $value);
Zend_Registry
Zend_Registry
Zend Framework手册 中文版
Zend_Rest
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Registry
  • 使用对象注册表（Registry）


Zend_Rest - Zend Framework Manual

使用对象注册表（Registry）
Zend Framework Reference
Zend Framework手册 中文版
Introduction

Zend_Rest

Table of Contents
  • Introduction
  • Zend_Rest_Client
  • Zend_Rest_Server
使用对象注册表（Registry）
Zend Framework Reference
Zend Framework手册 中文版
Introduction
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


Introduction - Zend Framework Manual

Zend_Rest
Zend_Rest
Zend Framework手册 中文版
Zend_Rest_Client

Introduction

REST Web Services use service-specific XML formats. These ad-hoc standards mean that 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.

Zend Framework provides both Client and Server capabilities, which, when used together allow for a much more "local" interface experience via virtual object property access. The Server component features automatic exposition of functions and classes using a meaningful and simple XML format. When accessing these services using the Client, it is possible to easily retrieve the return data from the remote call. Should you wish to use the client with a non-Zend_Rest_Server based service, it will still provide easier data access.

In addition to Zend_Rest_Server and Zend_Rest_Client components, Zend_Rest_Route and Zend_Rest_Controller classes are provided to aid routing REST requests to controllers.

Zend_Rest
Zend_Rest
Zend Framework手册 中文版
Zend_Rest_Client
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Rest
  • Introduction
  • Zend_Rest_Client
  • Zend_Rest_Server


Zend_Rest_Client - Zend Framework Manual

Introduction
Zend_Rest
Zend Framework手册 中文版
Zend_Rest_Server

Zend_Rest_Client

Introduction

Using the Zend_Rest_Client is very similar to using SoapClient objects (» SOAP web service extension). You can simply call the REST service procedures as Zend_Rest_Client methods. Specify the service's full address in the Zend_Rest_Client constructor.

Example #1 A basic REST request

  1. /**
  2. * Connect to framework.zend.com server and retrieve a greeting
  3. */
  4. $client = new Zend_Rest_Client('http://framework.zend.com/rest');
  5.
  6. echo $client->sayHello('Davey', 'Day')->get(); // "Hello Davey, Good Day"

Note: Differences in calling
 Zend_Rest_Client attempts to make remote methods look as much like native methods as possible, the only difference being that you must follow the method call with one of either get(), post(), put() or delete(). This call may be made via method chaining or in separate method calls:

  1. $client->sayHello('Davey', 'Day');
  2. echo $client->get();

Responses

All requests made using Zend_Rest_Client return a Zend_Rest_Client_Response object. This object has many properties that make it easier to access the results.

When the service is based on Zend_Rest_Server, Zend_Rest_Client can make several assumptions about the response, including response status (success or failure) and return type.

Example #2 Response Status

  1. $result = $client->sayHello('Davey', 'Day')->get();
  2.
  3. if ($result->isSuccess()) {
  4.     echo $result; // "Hello Davey, Good Day"
  5. }

In the example above, you can see that we use the request result as an object, to call isSuccess(), and then because of __toString(), we can simply echo the object to get the result. Zend_Rest_Client_Response will allow you to echo any scalar value. For complex types, you can use either array or object notation.

If however, you wish to query a service not using Zend_Rest_Server the Zend_Rest_Client_Response object will behave more like a SimpleXMLElement. However, to make things easier, it will automatically query the XML using XPath if the property is not a direct descendant of the document root element. Additionally, if you access a property as a method, you will receive the PHP value for the object, or an array of PHP value results.

Example #3 Using Technorati's Rest Service

  1. $technorati = new Zend_Rest_Client('http://api.technorati.com/bloginfo');
  2. $technorati->key($key);
  3. $technorati->url('http://pixelated-dreams.com');
  4. $result = $technorati->get();
  5. echo $result->firstname() .' '. $result->lastname();

Example #4 Example Technorati Response

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!-- generator="Technorati API version 1.0 /bloginfo" -->
  3. <!DOCTYPE tapi PUBLIC "-//Technorati, Inc.//DTD TAPI 0.02//EN"
  4.                       "http://api.technorati.com/dtd/tapi-002.xml">
  5. <tapi version="1.0">
  6.     <document>
  7.         <result>
  8.             <url>http://pixelated-dreams.com</url>
  9.             <weblog>
  10.                 <name>Pixelated Dreams</name>
  11.                 <url>http://pixelated-dreams.com</url>
  12.                 <author>
  13.                     <username>DShafik</username>
  14.                     <firstname>Davey</firstname>
  15.                     <lastname>Shafik</lastname>
  16.                 </author>
  17.                 <rssurl>
  18.                     http://pixelated-dreams.com/feeds/index.rss2
  19.                 </rssurl>
  20.                 <atomurl>
  21.                     http://pixelated-dreams.com/feeds/atom.xml
  22.                 </atomurl>
  23.                 <inboundblogs>44</inboundblogs>
  24.                 <inboundlinks>218</inboundlinks>
  25.                 <lastupdate>2006-04-26 04:36:36 GMT</lastupdate>
  26.                 <rank>60635</rank>
  27.             </weblog>
  28.             <inboundblogs>44</inboundblogs>
  29.             <inboundlinks>218</inboundlinks>
  30.         </result>
  31.     </document>
  32. </tapi>

Here we are accessing the firstname and lastname properties. Even though these are not top-level elements, they are automatically returned when accessed by name.

Note: Multiple items
 If multiple items are found when accessing a value by name, an array of SimpleXMLElements will be returned; accessing via method notation will return an array of PHP values.

Request Arguments

Unless you are making a request to a Zend_Rest_Server based service, chances are you will need to send multiple arguments with your request. This is done by calling a method with the name of the argument, passing in the value as the first (and only) argument. Each of these method calls returns the object itself, allowing for chaining, or "fluent" usage. The first call, or the first argument if you pass in more than one argument, is always assumed to be the method when calling a Zend_Rest_Server service.

Example #5 Setting Request Arguments

  1. $client = new Zend_Rest_Client('http://example.org/rest');
  2.
  3. $client->arg('value1');
  4. $client->arg2('value2');
  5. $client->get();
  6.
  7. // or
  8.
  9. $client->arg('value1')->arg2('value2')->get();

Both of the methods in the example above, will result in the following get args: ?method=arg&arg1=value1&arg=value1&arg2=value2

You will notice that the first call of $client->arg('value1'); resulted in both method=arg&arg1=value1 and arg=value1; this is so that Zend_Rest_Server can understand the request properly, rather than requiring pre-existing knowledge of the service.

Warning

Strictness of Zend_Rest_Client

Any REST service that is strict about the arguments it receives will likely fail using Zend_Rest_Client, because of the behavior described above. This is not a common practice and should not cause problems.

Introduction
Zend_Rest
Zend Framework手册 中文版
Zend_Rest_Server
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Rest
  • Introduction
  • Zend_Rest_Client
  • Zend_Rest_Server


Zend_Rest_Server - Zend Framework Manual

Zend_Rest_Client
Zend_Rest
Zend Framework手册 中文版
Zend_Search_Lucene

Zend_Rest_Server

Introduction

Zend_Rest_Server is intended as a fully-featured REST server.

REST Server Usage

Example #1 Basic Zend_Rest_Server Usage - Classes

  1. $server = new Zend_Rest_Server();
  2. $server->setClass('My_Service_Class');
  3. $server->handle();

Example #2 Basic Zend_Rest_Server Usage - Functions

  1. /**
  2. * Say Hello
  3. *
  4. * @param string $who
  5. * @param string $when
  6. * @return string
  7. */
  8. function sayHello($who, $when)
  9. {
  10.     return "Hello $who, Good $when";
  11. }
  12.
  13. $server = new Zend_Rest_Server();
  14. $server->addFunction('sayHello');
  15. $server->handle();

Calling a Zend_Rest_Server Service

To call a Zend_Rest_Server service, you must supply a GET/POST method argument with a value that is the method you wish to call. You can then follow that up with any number of arguments using either the name of the argument (i.e. "who") or using arg following by the numeric position of the argument (i.e. "arg1").

Note: Numeric index
 Numeric arguments use a 1-based index.

To call sayHello from the example above, you can use either:

?method=sayHello&who=Davey&when=Day

or:

?method=sayHello&arg1=Davey&arg2=Day

Sending A Custom Status

When returning values, to return a custom status, you may return an array with a status key.

Example #3 Returning Custom Status

  1. /**
  2. * Say Hello
  3. *
  4. * @param string $who
  5. * @param string $when
  6. * @return array
  7. */
  8. function sayHello($who, $when)
  9. {
  10.     return array('msg' => "An Error Occurred", 'status' => false);
  11. }
  12.
  13. $server = new Zend_Rest_Server();
  14. $server->addFunction('sayHello');
  15. $server->handle();

Returning Custom XML Responses

If you wish to return custom XML, simply return a DOMDocument, DOMElement or SimpleXMLElement object.

Example #4 Return Custom XML

  1. /**
  2. * Say Hello
  3. *
  4. * @param string $who
  5. * @param string $when
  6. * @return SimpleXMLElement
  7. */
  8. function sayHello($who, $when)
  9. {
  10.     $xml ='<?xml version="1.0" encoding="ISO-8859-1"?>
  11. <mysite>
  12.     <value>Hey $who! Hope you\'re having a good $when</value>
  13.     <code>200</code>
  14. </mysite>';
  15.
  16.     $xml = simplexml_load_string($xml);
  17.     return $xml;
  18. }
  19.
  20. $server = new Zend_Rest_Server();
  21. $server->addFunction('sayHello');
  22.
  23. $server->handle();

The response from the service will be returned without modification to the client.

Zend_Rest_Client
Zend_Rest
Zend Framework手册 中文版
Zend_Search_Lucene
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Rest
  • Introduction
  • Zend_Rest_Client
  • Zend_Rest_Server


Zend_Search_Lucene - Zend Framework Manual

Zend_Rest_Server
Zend Framework Reference
Zend Framework手册 中文版
概述

Zend_Search_Lucene

Table of Contents
  • 概述
  • 建立索引
  • 搜索索引
  • Query Language
  • 查询类型
  • 字符集
  • 扩展性
  • 与 Java Lucene 的互操作性
  • Advanced
  • Best Practices
Zend_Rest_Server
Zend Framework Reference
Zend Framework手册 中文版
概述
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


概述 - Zend Framework Manual

Zend_Search_Lucene
Zend_Search_Lucene
Zend Framework手册 中文版
建立索引

概述

简介

Zend_Search_Lucene 是一个完全由 PHP 5 编写的通用文本搜索引擎。由于其将索引保存在文件系统中而不需要数据库支持，因此它几乎可以为任何由 PHP 驱动的网站增加搜索能力。Zend_Search_Lucene 支持下列特性：

  • 具有排名功能的搜索——最符合要求的结果出现在最前面

  • 许多强大的查询类型：短语查询、通配符查询、近似查询、范围查询等 [1]

  • 搜索特定的字段，如标题、作者、内容，等等

Zend_Search_Lucene 来源于 Apache Lucene project。要了解关于 Lucene 的更多详情，请访问 http://lucene.apache.org/java/docs/。

文档和字段对象

Zend_Search_Lucene 把文档最为基本的索引主题。而文档(document)又分为若干被命名的字段(field)，字段中包含可供搜索的内容。

一个文档被表现为 Zend_Search_Lucene_Document 对象，这个对象包含了若干 Zend_Search_Lucene_Field 对象，用以表现相应的字段。

需要特别说明的是任意类型的信息都可以被加入索引中。应用程序描述信息或者元信息(metadata)可以被保存在文档字段中，并在搜索过程中与文档一起被检索。

控制这些索引是你的应用程序的责任。这意味着任意你的应用程序可以访问的数据来源都可以进行索引。例如，这些数据可以来自于文件系统、数据库或者是 HTML 表单，等等。

Zend_Search_Lucene_Field 类提供了一些静态方法用以创建具有不同特点的字段：

<?php
$doc = new Zend_Search_Lucene_Document();

// Field is not tokenized, but is indexed and stored within the index.
// Stored fields can be retrived from the index.
$doc->addField(Zend_Search_Lucene_Field::Keyword('doctype',
                                                 'autogenerated'));

// Field is not tokenized nor indexed, but is stored in the index.
$doc->addField(Zend_Search_Lucene_Field::UnIndexed('created',
                                                   time()));

// Binary String valued Field that is not tokenized nor indexed,
// but is stored in the index.
$doc->addField(Zend_Search_Lucene_Field::Binary('icon',
                                                $iconData));

// Field is tokenized and indexed, and is stored in the index.
$doc->addField(Zend_Search_Lucene_Field::Text('annotation',
                                              'Document annotation text'));

// Field is tokenized and indexed, but that is not stored in the index.
$doc->addField(Zend_Search_Lucene_Field::UnStored('contents',
                                                  'My document content'));

?>

你可以按照自己的需要给字段命名。名为“contents”的字段缺省的用于搜索。因此，将主要的文档内容放在这个字段中会是个好主意。

理解字段类型

  • Keyword 关键词字段是被保存和被索引的，意思是它们既可以被搜索，也可以在搜索结果中被显示。它们并没有以记号化的方式拆分为多个不同的词。在 Zend_Search_Lucene 中，枚举形的数据库字段通常可以很好的转化为关键词字段。

  • UnIndexed 不索引字段是不可搜索的，但是它们会在搜索结果中返回用于生成点击信息。数据库的时间戳、主键、文件系统的路径、以及其它标识是不索引字段的好的候选人。

  • Binary 二进制字段是不记号化和不被索引的，但是被保存以供生成点击信息。它们可以用于保存任何以二进制方式编码的信息，例如图标等等。

  • Text 文本字段是被保存的、被索引的和记号化的。文本字段适合用于保存像是主题、标题这样既能被搜索又能作为搜索结果返回的信息。

  • UnStored 不保存字段是记号化和被索引的，但并不保存在索引中。大量的文本信息最好使用这种字段类型。保存的数据在硬盘上创建了大量的索引，如果你需要搜索而不需要在搜索结果中显示这些数据，就使用不保存字段。当结合使用 Zend_Search_Lucene 索引和关系数据库时最适合使用不保存字段。你通过不保存字段索引大量数据用于搜索，并通过作为标识的特定字段从你的关系数据库中获取它们。

    Zend_Search_Lucene_Field 类型
    字段类型 | 保存 | 索引 | 记号化 | 二进制
    Keyword | 是 | 是 | 否 | 否
    UnIndexed | 是 | 否 | 否 | 否
    Binary | 是 | 否 | 否 | 是
    Text | 是 | 是 | 是 | 否
    UnStored | 否 | 是 | 是 | 否
[1] 目前只支持单项和多项查询。
Zend_Search_Lucene
Zend_Search_Lucene
Zend Framework手册 中文版
建立索引
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Search_Lucene
  • 概述
  • 建立索引
  • 搜索索引
  • Query Language
  • 查询类型
  • 字符集
  • 扩展性
  • 与 Java Lucene 的互操作性
  • Advanced
  • Best Practices


建立索引 - Zend Framework Manual

概述
Zend_Search_Lucene
Zend Framework手册 中文版
搜索索引

建立索引

创建新索引

在 Zend_Search_Lucene 模块和 Java Lucene 中实现了索引的创建和更新机制。你都可以使用。

下面的 PHP 代码提供了一个如何使用 Zend_Search_Lucene 索引 API 的例子：

<?php

// Setting the second argument to TRUE creates a new index
$index = new Zend_Search_Lucene('/data/my-index', true);

$doc = new Zend_Search_Lucene_Document();

// Store document URL to identify it in search result.
$doc->addField(Zend_Search_Lucene_Field::Text('url', $docUrl));

// Index document content
$doc->addField(Zend_Search_Lucene_Field::UnStored('contents', $docContent));

// Add document to the index.
$index->addDocument($doc);

// Write changes to the index.
$index->commit();
?>

在进行了 commit 提交操作之后，新添加的文档就可以被检索了。

Zend_Search_Lucene::commit() 会在脚本执行结束前以及任意搜索请求开始之前被自动调用。

每一次 commit() 调用产生新的索引分段。因此尽可能少的请求它。当然另一方面，在一步中提交大量的文档需要更多的内存。

字段分段管理优化是 Zend_Search_Lucene 未来要增强的内容。

更新索引

同样的过程可以用于更新现存的索引。唯一的区别是打开相应的索引是不需要第二个参数：

<?php

// Open existing index
$index = new Zend_Search_Lucene('/data/my-index');

$doc = new Zend_Search_Lucene_Document();
// Store document URL to identify it in search result.
$doc->addField(Zend_Search_Lucene_Field::Text('url', $docUrl));
// Index document content
$doc->addField(Zend_Search_Lucene_Field::UnStored('contents', $docContent));

// Add document to the index.
$index->addDocument($doc);

// Write changes to the index.
$index->commit();
?>

每一次 commit() 调用(显式的或者隐式的)产生新的索引分段。

Zend_Search_Lucene 不会自动管理分段。因此你应该关注分段的大小。一方面一个大的分段可能更加理想，另一方面在创建时需要更大的内存。

Lucene Java 和 Luke (Lucene Index Toolbox - » http://www.getopt.org/luke/)可以用于优化这个版本的 Zend_Search_Lucene 产生的索引。

概述
Zend_Search_Lucene
Zend Framework手册 中文版
搜索索引
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Search_Lucene
  • 概述
  • 建立索引
  • 搜索索引
  • Query Language
  • 查询类型
  • 字符集
  • 扩展性
  • 与 Java Lucene 的互操作性
  • Advanced
  • Best Practices


搜索索引 - Zend Framework Manual

建立索引
Zend_Search_Lucene
Zend Framework手册 中文版
Query Language

搜索索引

建立查询

有两种方式可以在索引中进行搜索。第一个方式是使用查询分析程序(Query Parser)来从字符串中创建查询。第二个方式通过 Zend_Search_Lucene API 提供了创建自己的查询的可能。

在选择使用查询分析程序之前，请考虑下面问题：

  1. 如果你使用程序生成查询字串并传递给查询分析程序，那么你最好考虑直接使用查询 API 来建立查询。换句话说，查询分析程序是为人为输入的文本设计的，而不是为程序生成的文本准备的。

  2. 非记号化字段最好直接加入查询中，而不是通过查询分析程序。如果一个字段的值是应用程序生成的，那么它应该按照这个条款进行查询。查询分析程序使用的机制，是设计来转换人为输入的文本的。像日期、关键词等等，都可以认为是程序生成的信息。

  3. 在查询表单中，用于产生文本的字段应该是用查询分析程序。所有其它的诸如日期范围、关键词等，最好通过查询 API 直接加入查询中。一个具有一组取之范围的字段，可以通过下拉菜单来实现而不应该加入需要被分析的查询字串中，而不是增加一个查询项。

两种途径都使用同样的 API 方法来搜索索引：

<?php

require_once('Zend/Search/Lucene.php');

$index = new Zend_Search_Lucene('/data/my_index');

$index->find($query);

?>
方法 Zend_Search_Lucene::find() 自动检查输入类型并使用查询分析程序从字符串建立适当的 Zend_Search_Lucene_Search_Query 对象。

需要特别注意的是 find() 是大小写敏感的。默认的，LuceneIndexCreation.jar 标准化所有文档为小写。可以通过命令行来关闭这个设置(输入不带参数的 LuceneIndexCreation.jar 命令来获取帮助)。提供给 find() 的文本大小写必须和索引中的相匹配。如果索引被正常设置为全小写，那么提供给 find() 的文本必须用 strtolower()处理，否则它可能无法被匹配。

搜索结果

搜索结果是一个 Zend_Search_Lucene_Search_QueryHit 对象数组。每一个数组元素具有两个属性： $hit->document 是索引中的文档编号，$hit->score 是其在搜索结果中的分值。搜索结果是按照分值排序的(最高分的搜索结果位于最前面)。

Zend_Search_Lucene_Search_QueryHit 对象还能将 Zend_Search_Lucene_Document 中的各个字段作为属性陈列出来。在下面这个例子中，搜索结果相应的文档具有两个字段：title 和 author。

<?php

require_once('Zend/Search/Lucene.php');

$index = new Zend_Search_Lucene('/data/my_index');

$hits = $index->find($query);

foreach ($hits as $hit) {
    echo $hit->id;
    echo $hit->score;

    echo $hit->title;
    echo $hit->author;
}

?>

可选的，原始的 Zend_Search_Lucene_Document 对象可以从 Zend_Search_Lucene_Search_QueryHit 获得。你可以使用索引对象的 getDocument() 方法来获取文档进行了索引的部分并接着使用 getFieldValue() 方法。

<?php

require_once('Zend/Search/Lucene.php');

$index = new Zend_Search_Lucene('/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 a Zend_Search_Lucene_Field object
    // from the Zend_Search_Lucene_Document
    echo $document->getField('title');

    // return the string value of the Zend_Search_Lucene_Field object
    echo $document->getFieldValue('title');

    // same as getFieldValue()
    echo $document->title;
}

?>
能够获取的 Zend_Search_Lucene_Document 对象的字段是在进行索引的时候决定的。由索引创建程序(例如：LuceneIndexCreation.jar)在文档中建立的文档字段要么是被索引的，要么是被索引并保存的。

请注意，文档标识(在本例中是'path')也保存在索引中，它必须被提取出来。

结果评分

Zend_Search_Lucene 使用和 Java Lucene 一样的评分算法。搜索结果是按照分值进行排序的。分值越大，相应的搜索结果点击排在排位越靠前。

不同的分值意味着一篇文档相比另一篇更能匹配查询要求。

粗略的说，包含更多的搜索项或短语的搜索结果，将会具有更高的分值。

可以通过 score 属性获取一个搜索结果的分值：

<?php
$hits = $index->find($query);

foreach ($hits as $hit) {
    echo $hit->id;
    echo $hit->score;
}

?>

类 Zend_Search_Lucene_Search_Similarity 用于计算分值。请参阅“扩展性”中“评分算法”一节了解详情。

建立索引
Zend_Search_Lucene
Zend Framework手册 中文版
Query Language
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Search_Lucene
  • 概述
  • 建立索引
  • 搜索索引
  • Query Language
  • 查询类型
  • 字符集
  • 扩展性
  • 与 Java Lucene 的互操作性
  • Advanced
  • Best Practices


Query Language - Zend Framework Manual

搜索索引
Zend_Search_Lucene
Zend Framework手册 中文版
查询类型

Query Language

Java Lucene and Zend_Search_Lucene provide quite powerful query languages.

These languages are mostly the same with some minor differences, which are mentioned below.

Full Java Lucene query language syntax documentation can be found » here.

Terms

A query is broken up into terms and operators. There are three types of terms: Single Terms, Phrases, and Subqueries.

A Single Term is a single word such as "test" or "hello".

A Phrase is a group of words surrounded by double quotes such as "hello dolly".

A Subquery is a query surrounded by parentheses such as "(hello dolly)".

Multiple terms can be combined together with boolean operators to form complex queries (see below).

Fields

Lucene supports fields of data. When performing a search you can either specify a field, or use the default field. The field names depend on indexed data and default field is defined by current settings.

The first and most significant difference from Java Lucene is that terms are searched through all fields by default.

There are two static methods in the Zend_Search_Lucene class which allow the developer to configure these settings:

  1. $defaultSearchField = Zend_Search_Lucene::getDefaultSearchField();
  2. ...
  3. Zend_Search_Lucene::setDefaultSearchField('contents');

The NULL value indicated that the search is performed across all fields. It's the default setting.

You can search specific fields by typing the field name followed by a colon ":" followed by the term you are looking for.

As an example, let's assume a Lucene index contains two fields- title and text- with text as the default field. If you want to find the document entitled "The Right Way" which contains the text "don't go this way", you can enter:

  1. title:"The Right Way" AND text:go

or

  1. title:"Do it right" AND go

Because "text" is the default field, the field indicator is not required.

Note: The field is only valid for the term, phrase or subquery that it directly precedes, so the query

  1. title:Do it right
Will only find "Do" in the title field. It will find "it" and "right" in the default field (if the default field is set) or in all indexed fields (if the default field is set to NULL).

Wildcards

Lucene supports single and multiple character wildcard searches within single terms (but not within phrase queries).

To perform a single character wildcard search use the "?" symbol.

To perform a multiple character wildcard search use the "*" symbol.

The single character wildcard search looks for string that match the term with the "?" replaced by any single character. For example, to search for "text" or "test" you can use the search:

  1. te?t

Multiple character wildcard searches look for 0 or more characters when matching strings against terms. For example, to search for test, tests or tester, you can use the search:

  1. test*

You can use "?", "*" or both at any place of the term:

  1. *wr?t*
It searches for "write", "wrote", "written", "rewrite", "rewrote" and so on.

Starting from ZF 1.7.7 wildcard patterns need some non-wildcard prefix. Default prefix length is 3 (like in Java Lucene). So "*", "te?t", "*wr?t*" terms will cause an exception[1] Zend_Search_Lucene_Search_QueryParserExceptionZend_Search_Lucene_Exception.

It can be altered using Zend_Search_Lucene_Search_Query_Wildcard::getMinPrefixLength() and Zend_Search_Lucene_Search_Query_Wildcard::setMinPrefixLength() methods.

Term Modifiers

Lucene supports modifying query terms to provide a wide range of searching options.

"~" modifier can be used to specify proximity search for phrases or fuzzy search for individual terms.

Range Searches

Range queries allow the developer or user to match documents whose field(s) values are between the lower and upper bound specified by the range query. Range Queries can be inclusive or exclusive of the upper and lower bounds. Sorting is performed lexicographically.

  1. mod_date:[20020101 TO 20030101]
This will find documents whose mod_date fields have values between 20020101 and 20030101, inclusive. Note that Range Queries are not reserved for date fields. You could also use range queries with non-date fields:
  1. title:{Aida TO Carmen}
This will find all documents whose titles would be sorted between Aida and Carmen, but not including Aida and Carmen.

Inclusive range queries are denoted by square brackets. Exclusive range queries are denoted by curly brackets.

If field is not specified then Zend_Search_Lucene searches for specified interval through all fields by default.

  1. {Aida TO Carmen}

Fuzzy Searches

Zend_Search_Lucene as well as Java Lucene supports fuzzy searches based on the Levenshtein Distance, or Edit Distance algorithm. To do a fuzzy search use the tilde, "~", symbol at the end of a Single word Term. For example to search for a term similar in spelling to "roam" use the fuzzy search:

  1. roam~
This search will find terms like foam and roams. Additional (optional) parameter can specify the required similarity. The value is between 0 and 1, with a value closer to 1 only terms with a higher similarity will be matched. For example:
  1. roam~0.8
The default that is used if the parameter is not given is 0.5.

Matched terms limitation

Wildcard, range and fuzzy search queries may match too many terms. It may cause incredible search performance downgrade.

So Zend_Search_Lucene sets a limit of matching terms per query (subquery). This limit can be retrieved and set using Zend_Search_Lucene::getTermsPerQueryLimit()/Zend_Search_Lucene::setTermsPerQueryLimit($limit) methods.

Default matched terms per query limit is 1024.

Proximity Searches

Lucene supports finding words from a phrase that are within a specified word distance in a string. To do a proximity search use the tilde, "~", symbol at the end of the phrase. For example to search for a "Zend" and "Framework" within 10 words of each other in a document use the search:

  1. "Zend Framework"~10

Boosting a Term

Java Lucene and Zend_Search_Lucene provide the relevance level of matching documents based on the terms found. To boost the relevance of a term use the caret, "^", symbol with a boost factor (a number) at the end of the term you are searching. The higher the boost factor, the more relevant the term will be.

Boosting allows you to control the relevance of a document by boosting individual terms. For example, if you are searching for

  1. PHP framework
and you want the term "PHP" to be more relevant boost it using the ^ symbol along with the boost factor next to the term. You would type:
  1. PHP^4 framework
This will make documents with the term PHP appear more relevant. You can also boost phrase terms and subqueries as in the example:
  1. "PHP framework"^4 "Zend Framework"
By default, the boost factor is 1. Although the boost factor must be positive, it may be less than 1 (e.g. 0.2).

Boolean Operators

Boolean operators allow terms to be combined through logic operators. Lucene supports AND, "+", OR, NOT and "-" as Boolean operators. Java Lucene requires boolean operators to be ALL CAPS. Zend_Search_Lucene does not.

AND, OR, and NOT operators and "+", "-" defines two different styles to construct boolean queries. Unlike Java Lucene, Zend_Search_Lucene doesn't allow these two styles to be mixed.

If the AND/OR/NOT style is used, then an AND or OR operator must be present between all query terms. Each term may also be preceded by NOT operator. The AND operator has higher precedence than the OR operator. This differs from Java Lucene behavior.

AND

The AND operator means that all terms in the "AND group" must match some part of the searched field(s).

To search for documents that contain "PHP framework" and "Zend Framework" use the query:

  1. "PHP framework" AND "Zend Framework"

OR

The OR operator divides the query into several optional terms.

To search for documents that contain "PHP framework" or "Zend Framework" use the query:

  1. "PHP framework" OR "Zend Framework"

NOT

The NOT operator excludes documents that contain the term after NOT. But an "AND group" which contains only terms with the NOT operator gives an empty result set instead of a full set of indexed documents.

To search for documents that contain "PHP framework" but not "Zend Framework" use the query:

  1. "PHP framework" AND NOT "Zend Framework"

&&, ||, and ! operators

&&, ||, and ! may be used instead of AND, OR, and NOT notation.

+

The "+" or required operator stipulates that the term after the "+" symbol must match the document.

To search for documents that must contain "Zend" and may contain "Framework" use the query:

  1. +Zend Framework

-

The "-" or prohibit operator excludes documents that match the term after the "-" symbol.

To search for documents that contain "PHP framework" but not "Zend Framework" use the query:

  1. "PHP framework" -"Zend Framework"

No Operator

If no operator is used, then the search behavior is defined by the "default boolean operator".

This is set to OR by default.

That implies each term is optional by default. It may or may not be present within document, but documents with this term will receive a higher score.

To search for documents that requires "PHP framework" and may contain "Zend Framework" use the query:

  1. +"PHP framework" "Zend Framework"

The default boolean operator may be set or retrieved with the Zend_Search_Lucene_Search_QueryParser::setDefaultOperator($operator) and Zend_Search_Lucene_Search_QueryParser::getDefaultOperator() methods, respectively.

These methods operate with the Zend_Search_Lucene_Search_QueryParser::B_AND and Zend_Search_Lucene_Search_QueryParser::B_OR constants.

Grouping

Java Lucene and Zend_Search_Lucene support using parentheses to group clauses to form sub queries. This can be useful if you want to control the precedence of boolean logic operators for a query or mix different boolean query styles:

  1. +(framework OR library) +php
Zend_Search_Lucene supports subqueries nested to any level.

Field Grouping

Lucene also supports using parentheses to group multiple clauses to a single field.

To search for a title that contains both the word "return" and the phrase "pink panther" use the query:

  1. title:(+return +"pink panther")

Escaping Special Characters

Lucene supports escaping special characters that are used in query syntax. The current list of special characters is:

+ - && || ! ( ) { } [ ] ^ " ~ * ? : \

+ and - inside single terms are automatically treated as common characters.

For other instances of these characters use the \ before each special character you'd like to escape. For example to search for (1+1):2 use the query:

  1. \(1\+1\)\:2

[1] Please note, that it's not a , but a . It's thrown during query rewrite (execution) operation.
搜索索引
Zend_Search_Lucene
Zend Framework手册 中文版
查询类型
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Search_Lucene
  • 概述
  • 建立索引
  • 搜索索引
  • Query Language
  • 查询类型
  • 字符集
  • 扩展性
  • 与 Java Lucene 的互操作性
  • Advanced
  • Best Practices


查询类型 - Zend Framework Manual

Query Language
Zend_Search_Lucene
Zend Framework手册 中文版
字符集

查询类型

单项查询

单项查询用于搜索一个搜索项。

两种搜索方式都可以用于单项查询。

查询字串：

    $hits = $index->find('word1');

或者

通过 API 创建查询：

<?php

    $term  = new Zend_Search_Lucene_Index_Term('word1');
    $query = new Zend_Search_Lucene_Search_Query_Term($term);
    $hits  = $index->find($query);

?>

多项查询

多项查询用于搜索一组搜索项。

每一个搜索项可以被定义为必须的、禁止的或者既不必须也不禁止(可选)的。

  • 必须的意思是文档如果不匹配这个搜索项，那么它就不匹配整个查询；

  • 禁止的意思是文档如果匹配这个搜索项，那么它就不匹配整个查询；

  • 可选的，这种情况下文档对搜索项的匹配既不是必须的也不是禁止的。无论如何，文档必须匹配至少一个搜索项才能匹配整个查询。

这意味着，如果一个包含必须的搜索项的查询中加入了可选的搜索项，返回的搜索结果集合是一样的，但是那些包含可选搜索项的搜索结果，将会上升到结果清单的前面。

两种搜索方式都可以用于单项查询。

查询字串：

<?php

$hits = $index->find('+word1 author:word2 -word3');

?>

  • '+' 用于定义必须的搜索项。

  • '-' 用于定义禁止的搜索项。

  • 'field:' 用于指明要搜索的字段。如果没有提供，则默认的是'contents'。

或者

通过 API 创建查询：

<?php

    $query = new Zend_Search_Lucene_Search_Query_MultiTerm();

    $query->addTerm(new Zend_Search_Lucene_Index_Term('word1'), true);
    $query->addTerm(new Zend_Search_Lucene_Index_Term('word2'), null);
    $query->addTerm(new Zend_Search_Lucene_Index_Term('word3'), false);

    $hits  = $index->find($query);

?>

$signs 数组包含了搜索项的类型：

  • true 用于定义必须的搜索项。

  • false 用于定义禁止的搜索项。

  • null 用于定义既不必须也不禁止的搜索项。

短语查询

短语查询用于搜索短语。

短语查询非常灵活，既可以搜索精确的短语，也可以搜索模糊的短语。精确短语可以包含搜索项和空隙(译注，所谓空隙也就是支持形如“word1 ... word2”的短语)。(可以使用分需程序生成以用于不同的用途。此外，搜索项可以被复制以提升该搜索项的权重或着一些同义词可以放在相同的地方。)因此目前短语查询只能通过 API 创建：

<?php
$query1 = new Zend_Search_Lucene_Search_Query_Phrase();

// Add 'word1' at 0 relative position.
$query1->addTerm(new Zend_Search_Lucene_Index_Term('word1'));

// Add 'word2' at 1 relative position.
$query1->addTerm(new Zend_Search_Lucene_Index_Term('word2'));

// Add 'word3' at 3 relative position.
$query1->addTerm(new Zend_Search_Lucene_Index_Term('word3'), 3);

...

$query2 = new Zend_Search_Lucene_Search_Query_Phrase(
                array('word1', 'word2', 'word3'), array(0,1,3));

...

// Query without a gap.
$query3 = new Zend_Search_Lucene_Search_Query_Phrase(
                array('word1', 'word2', 'word3'));

...

$query4 = new Zend_Search_Lucene_Search_Query_Phrase(
                array('word1', 'word2'), array(0,1), 'annotation');

?>

短语查询可以使用类的构造方法一次性创建，也可以使用 Zend_Search_Lucene_Search_Query_Phrase::addTerm() 方法一步步的创建。

类 Zend_Search_Lucene_Search_Query_Phrase 的构造方法有三个可选的参数：

Zend_Search_Lucene_Search_Query_Phrase([array $terms[, array $offsets[, string $field]]]);

$terms 是字符串数组，包含一组短语搜索项。如果它被省略或者为 null，那么将会创建一个空查询。

$offsets 是一个整数数组，包含短语搜索项的偏移值。如果它被省略或者为 null，那么搜索项的位置被认为是 array(0, 1, 2, 3, ...)。

$field 是一个字符串，表示要搜索的文档字段。如果它被省略或者为 null，那么默认的字段会被搜索。在这个版本的 Zend_Search_Lucene 中是“contents”，但是下个版本中计划变更为“any field”。

因此：

$query = new Zend_Search_Lucene_Search_Query_Phrase(array('zend', 'framework'));
将会搜索短语'zend framework'。
<$query = new Zend_Search_Lucene_Search_Query_Phrase(array('zend', 'download'), array(0, 2));
将会搜索短语“zend ????? download”并匹配'zend platform download'、 'zend studio download'、 'zend core download'、 'zend framework download'这样的内容。
$query = new Zend_Search_Lucene_Search_Query_Phrase(array('zend', 'framework'), null, 'title');
将会搜索在'title'字段中搜索短语“zend framework”。

方法 Zend_Search_Lucene_Search_Query_Phrase::addTerm() 有两个参数。必须的 Zend_Search_Lucene_Index_Term 对象和可选的位置：

Zend_Search_Lucene_Search_Query_Phrase::addTerm(Zend_Search_Lucene_Index_Term $term[, integer $position]);

$term 描述了短语中的下一个搜索项。它必须位于上一个搜索项同样的字段中。否则将会抛出异常。

$position 指出了它的位置。

因此：

$query = new Zend_Search_Lucene_Search_Query_Phrase();
$query->addTerm(new Zend_Search_Lucene_Index_Term('zend'));
$query->addTerm(new Zend_Search_Lucene_Index_Term('framework'));
将会搜索短语'zend framework'。
$query = new Zend_Search_Lucene_Search_Query_Phrase();
$query->addTerm(new Zend_Search_Lucene_Index_Term('zend'), 0);
$query->addTerm(new Zend_Search_Lucene_Index_Term('framework'), 2);
将会搜索短语'zend ????? download'并匹配'zend platform download'、 'zend studio download'、 'zend core download'、 'zend framework download'这样的内容。
$query = new Zend_Search_Lucene_Search_Query_Phrase();
$query->addTerm(new Zend_Search_Lucene_Index_Term('zend', 'title'));
$query->addTerm(new Zend_Search_Lucene_Index_Term('framework', 'title'));
将会搜索在'title'字段中搜索短语“zend framework”。

模糊因子设置了查询短语中两个词之间允许出现的其它词的数量。如果是 0，那么这是一个精确短语搜索。如果是一个较大的值，那么这工作起来像是具有(WITHIN)或者附近(NEAR)操作。

模糊因子事实上是一个“编辑距离”，表示移动搜索项移动到查询短语以外的位置上相对应的移动单位。例如，交换两个词的顺序需要两次移动(一次把一个词放到另一个前面)，因此要允许短语的重新排序，模糊因子至少必须为 2。

更精确的匹配相比更模糊的匹配得分更高，因此搜索结果将按照精确度排序。模糊因子默认为 0，也就是需要精确匹配。

模糊因子可以在查询创建后赋值：

<?php

// Query without a gap.
$query = new Zend_Search_Lucene_Search_Query_Phrase(array('word1', 'word2'));

// Search for 'word1 word2', 'word1 ... word2'
$query->setSlop(1);
$hits1 = $index->find($query);

// Search for 'word1 word2', 'word1 ... word2',
// 'word1 ... ... word2', 'word2 word1'
$query->setSlop(2);
$hits2 = $index->find($query);

?>
Query Language
Zend_Search_Lucene
Zend Framework手册 中文版
字符集
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Search_Lucene
  • 概述
  • 建立索引
  • 搜索索引
  • Query Language
  • 查询类型
  • 字符集
  • 扩展性
  • 与 Java Lucene 的互操作性
  • Advanced
  • Best Practices


字符集 - Zend Framework Manual

查询类型
Zend_Search_Lucene
Zend Framework手册 中文版
扩展性

字符集

UTF-8 和单字节字符集支持

被设计于工作在 UTF-8 字符集下。索引文件在 Java 的"modified UTF-8 encoding"编码下保存文件。Zend_Search_Lucene 内核完全支持它，只有一处例外。 [1]

然而，各类文本和查询分析程序使用 ctype_alpha() 来进行文本和查询的记号化处理。而 ctype_alpha() 不支持 UTF-8，在不久的将来需要被替换为别的什么机制。

在此之前我们强烈推荐将你的数据转化成 ASCII 表示 [2] (不管是存储原始文档，或者进行搜索)：

<?php
$doc = new Zend_Search_Lucene_Document();
...
$docText = iconv('ISO-8859-1', 'ASCII//TRANSLIT', $docText);
$doc->addField(Zend_Search_Lucene_Field::UnStored('contents', $docText));

...

$query = iconv('', 'ASCII//TRANSLIT', $query);
$hits = $index->find($query);
?>
[1] Zend_Search_Lucene 只支持基本多语言平面(Basic Multilingual Plane, BMP)字符集(从 0x0000 到 0xFFFF)，不支持辅助字符集(supplementary characters)(那些代码指针大于 0xFFFF 的字符) Java 2 通过一对两个 16 位字符的值来表示这些字符，第一个来自高半代理(high-surrogates)区(0xD800-0xDBFF)，第二个来自低半代理(low- surrogates)区(0xDC00-0xDFFF)。它们将常用的 UTF-8 字符编码为 6 个字节。而标准的 UTF-8 通过四个字节来表示附加的字符。 (译注：有关信息请参考 Unicode 标准。可能大家更想知道的是 BMP 中是否支持中文，答案是肯定的。事实上 BMP 中 CJK 字符集所占的比例最高。)
[2] 如果数据包含非 ASCII 字符或者来自 UTF-8。
查询类型
Zend_Search_Lucene
Zend Framework手册 中文版
扩展性
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Search_Lucene
  • 概述
  • 建立索引
  • 搜索索引
  • Query Language
  • 查询类型
  • 字符集
  • 扩展性
  • 与 Java Lucene 的互操作性
  • Advanced
  • Best Practices


扩展性 - Zend Framework Manual

字符集
Zend_Search_Lucene
Zend Framework手册 中文版
与 Java Lucene 的互操作性

扩展性

文本分析

Zend_Search_Lucene_Analysis_Analyzer 类被索引建立程序用于记号化文档的文本字段。

Zend_Search_Lucene_Analysis_Analyzer::getDefault() 方法和 Zend_Search_Lucene_Analysis_Analyzer::setDefault() 方法用于获取和设置默认的分析程序。

因此你可以使用你自己的文本分析程序或者从预设的分析程序中选择一个： Zend_Search_Lucene_Analysis_Analyzer_Common_Text 和 Zend_Search_Lucene_Analysis_Analyzer_Common_Text_CaseInsensitive(缺省的)。两者都把记号解释为一个字母序列。 Zend_Search_Lucene_Analysis_Analyzer_Common_Text_CaseInsensitive将记号转化为小写。

使用下面代码更换分析程序：

<?php

Zend_Search_Lucene_Analysis_Analyzer::setDefault(
    new Zend_Search_Lucene_Analysis_Analyzer_Common_Text());
...
$index->addDocument($doc);

?>

Zend_Search_Lucene_Analysis_Analyzer_Common类设计来作为所有自定义分析程序的祖先。用户可以只定义 tokenize()方法，它将字符串输入数据变成记号数组并返回。

方法 tokenize() 应该针对所有记号应用方法 normalize()。这样可以在你的分析程序中允许使用记号过滤。

这里是一个自定义分析程序的例子，它将单词变成数字作为搜索项：

Example #1 自定义文本分析程序

<?php
/** Here is a custome text analyser, which treats words with digits as one term */

/** Zend_Search_Lucene_Analysis_Analyzer_Common */
require_once 'Zend/Search/Lucene/Analysis/Analyzer/Common.php';

class My_Analyzer extends Zend_Search_Lucene_Analysis_Analyzer_Common
{
    /**
     * Tokenize text to a terms
     * Returns array of Zend_Search_Lucene_Analysis_Token objects
     *
     * @param string $data
     * @return array
     */
    public function tokenize($data)
    {
        $tokenStream = array();

        $position = 0;
        while ($position < strlen($data)) {
            // skip white space
            while ($position < strlen($data) && !ctype_alpha($data{$position}) && !ctype_digit($data{$position})) {
                $position++;
            }

            $termStartPosition = $position;

            // read token
            while ($position < strlen($data) && (ctype_alpha($data{$position}) || ctype_digit($data{$position}))) {
                $position++;
            }

            // Empty token, end of stream.
            if ($position == $termStartPosition) {
                break;
            }

            $token = new Zend_Search_Lucene_Analysis_Token(substr($data,
                                             $termStartPosition,
                                             $position-$termStartPosition),
                                      $termStartPosition,
                                      $position);
            $tokenStream[] = $this->normalize($token);
        }

        return $tokenStream;
    }
}

Zend_Search_Lucene_Analysis_Analyzer::setDefault(
    new My_Analyzer());

?>

评分算法

查询 q 的在文档 d 中的分值 score 定义如下：

score(q,d) = sum( tf(t in d) * idf(t) * getBoost(t.field in d) * lengthNorm(t.field in d) ) * coord(q,d) * queryNorm(q)

tf(t in d) - Zend_Search_Lucene_Search_Similarity::tf($freq) - 基于搜索项或者短语在文档中出现次数的分值因子。

idf(t) - Zend_Search_Lucene_Search_SimilaritySimilarity::tf($term, $reader) - 针对特定索引的简单搜索项的分值因子。

getBoost(t.field in d) - 针对搜索项字段的增益因子。

lengthNorm($term) - 对一个给定字段，其中包含的搜索项的总数的标准值。这个值保存在索引中。这些值和字段增益一起，保存在索引中，通过搜索代码和每一个搜索结果的每一个字段的分值相乘。

匹配较长的字段精度较低，所以这个实现方法通常在 numTikuns 较大时返回较小的分值，而在 numTokens 较小时返回较大的分值。

coord(q,d) - Zend_Search_Lucene_Search_Similarity::coord($overlap, $maxOverlap) - 基于文档包含的所有查询搜索项碎片的分值因子。

出现大部分的查询搜索项表示更好的匹配查询，所以这个实现方法通常当这些参数的比率较大时返回较大的分值，而这些比率较小时返回较小的分值。

queryNorm(q) - 对给定的查询，所有查询搜索项的权重的总和的标准值。这个值用于和每一个查询搜索项相乘。

这对于定级没有帮助，而仅仅是尝试为不同的查询建立可比较的评分。

你可以通过自定义 Similatity 类来定制评分算法。可以按照下面的定义来扩展 Zend_Search_Lucene_Search_Similarity 类，然后使用 Zend_Search_Lucene_Search_Similarity::setDefault($similarity); 方法来将其设置为缺省的评分算法。

<?php

class MySimilarity extends Zend_Search_Lucene_Search_Similarity {
    public function lengthNorm($fieldName, $numTerms) {
        return 1.0/sqrt($numTerms);
    }

    public function queryNorm($sumOfSquaredWeights) {
        return 1.0/sqrt($sumOfSquaredWeights);
    }

    public function tf($freq) {
        return sqrt($freq);
    }

    /**
     * It's not used now. Computes the amount of a sloppy phrase match,
     * based on an edit distance.
     */
    public function sloppyFreq($distance) {
        return 1.0;
    }

    public function idfFreq($docFreq, $numDocs) {
        return log($numDocs/(float)($docFreq+1)) + 1.0;
    }

    public function coord($overlap, $maxOverlap) {
        return $overlap/(float)$maxOverlap;
    }
}

$mySimilarity = new MySimilarity();
Zend_Search_Lucene_Search_Similarity::setDefault($mySimilarity);

?>

存储容器

抽象类 Zend_Search_Lucene_Storage_Directory 定义了目录功能。

Zend_Search_Lucene 构造方法使用字符串或者 Zend_Search_Lucene_Storage_Directory 对象作为输入。

Zend_Search_Lucene_Storage_Directory_Filesystem 类实现了针对文件系统的目录功能。

如果字符串被用于 Zend_Search_Lucene 构造方法的输入，那么索引阅读程序(Zend_Search_Lucene 对象)认为它是一个文件系统路径并自行实例化 Zend_Search_Lucene_Storage_Directory_Filesystem 对象。

你可以通过扩展 Zend_Search_Lucene_Storage_Directory 类定义自己的目录实现。

Zend_Search_Lucene_Storage_Directory 的方法：

<?php

abstract class Zend_Search_Lucene_Storage_Directory {
/**
 * Closes the store.
 *
 * @return void
 */
abstract function close();

/**
 * Creates a new, empty file in the directory with the given $filename.
 *
 * @param string $name
 * @return void
 */
abstract function createFile($filename);

/**
 * Removes an existing $filename in the directory.
 *
 * @param string $filename
 * @return void
 */
abstract function deleteFile($filename);

/**
 * Returns true if a file with the given $filename exists.
 *
 * @param string $filename
 * @return boolean
 */
abstract function fileExists($filename);

/**
 * Returns the length of a $filename in the directory.
 *
 * @param string $filename
 * @return integer
 */
abstract function fileLength($filename);

/**
 * Returns the UNIX timestamp $filename was last modified.
 *
 * @param string $filename
 * @return integer
 */
abstract function fileModified($filename);

/**
 * Renames an existing file in the directory.
 *
 * @param string $from
 * @param string $to
 * @return void
 */
abstract function renameFile($from, $to);

/**
 * Sets the modified time of $filename to now.
 *
 * @param string $filename
 * @return void
 */
abstract function touchFile($filename);

/**
 * Returns a Zend_Search_Lucene_Storage_File object for a given $filename in the directory.
 *
 * @param string $filename
 * @return Zend_Search_Lucene_Storage_File
 */
abstract function getFileObject($filename);

}

?>

Zend_Search_Lucene_Storage_Directory 类的 getFileObject($filename) 方法返回 Zend_Search_Lucene_Storage_File 对象。

Zend_Search_Lucene_Storage_File 抽象类实现了文件抽象和原始的索引文件读取。

你还必须扩展 Zend_Search_Lucene_Storage_File 类以建立自己的目录实现。

Zend_Search_Lucene_Storage_File 类中只有两个方法是你必须重载的：

<?php

class MyFile extends Zend_Search_Lucene_Storage_File {
    /**
     * Sets the file position indicator and advances the file pointer.
     * The new position, measured in bytes from the beginning of the file,
     * is obtained by adding offset to the position specified by whence,
     * whose values are defined as follows:
     * SEEK_SET - Set position equal to offset bytes.
     * SEEK_CUR - Set position to current location plus offset.
     * SEEK_END - Set position to end-of-file plus offset. (To move to
     * a position before the end-of-file, you need to pass a negative value
     * in offset.)
     * Upon success, returns 0; otherwise, returns -1
     *
     * @param integer $offset
     * @param integer $whence
     * @return integer
     */
    public function seek($offset, $whence=SEEK_SET) {
        ...
    }

    /**
     * Read a $length bytes from the file and advance the file pointer.
     *
     * @param integer $length
     * @return string
     */
    protected function _fread($length=1) {
        ...
    }
}

?>

字符集
Zend_Search_Lucene
Zend Framework手册 中文版
与 Java Lucene 的互操作性
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Search_Lucene
  • 概述
  • 建立索引
  • 搜索索引
  • Query Language
  • 查询类型
  • 字符集
  • 扩展性
  • 与 Java Lucene 的互操作性
  • Advanced
  • Best Practices


与 Java Lucene 的互操作性 - Zend Framework Manual

扩展性
Zend_Search_Lucene
Zend Framework手册 中文版
Advanced

与 Java Lucene 的互操作性

文件格式

Zend_Search_Lucene 的索引文件格式和 1.4 或更高版本的 Java Lucene 二进制兼容。

关于文件格式的更详细的描述在这里： http://lucene.apache.org/java/docs/fileformats.html。 [1]

索引目录

在创建了索引之后，索引目录中将包含下列文件：

  • segments 文件是一个索引分段的清单。

  • *.cfs 文件包含索引分段。请注意！优化了的索引总是只有一个分段。

  • deletable 文件是一个不再被索引使用但是无法删除的文件清单。

Java 源代码

下面的 Java 程序提供了一个如何使用 Java Lucene 索引文件的例子：

/**
* Index creation:
*/
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.document.*;

import java.io.*

...

IndexWriter indexWriter = new IndexWriter("/data/my_index",
                                          new SimpleAnalyzer(), true);

...

String filename = "/path/to/file-to-index.txt"
File f = new File(filename);

Document doc = new Document();
doc.add(Field.Text("path", filename));
doc.add(Field.Keyword("modified",DateField.timeToString(f.lastModified())));
doc.add(Field.Text("author", "unknown"));
FileInputStream is = new FileInputStream(f);
Reader reader = new BufferedReader(new InputStreamReader(is));
doc.add(Field.Text("contents", reader));

indexWriter.addDocument(doc);
[1] 当前支持的 Lucene 索引文件格式版本是 v2.3（从ZF 1.6 版开始）。
扩展性
Zend_Search_Lucene
Zend Framework手册 中文版
Advanced
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Search_Lucene
  • 概述
  • 建立索引
  • 搜索索引
  • Query Language
  • 查询类型
  • 字符集
  • 扩展性
  • 与 Java Lucene 的互操作性
  • Advanced
  • Best Practices


Advanced - Zend Framework Manual

与 Java Lucene 的互操作性
Zend_Search_Lucene
Zend Framework手册 中文版
Best Practices

Advanced

Starting from 1.6, handling index format transformations

Zend_Search_Lucene component works with Java Lucene 1.4-1.9, 2.1 and 2.3 index formats.

Current index format may be requested using $index->getFormatVersion() call. It returns one of the following values:

  • Zend_Search_Lucene::FORMAT_PRE_2_1 for Java Lucene 1.4-1.9 index format.

  • Zend_Search_Lucene::FORMAT_2_1 for Java Lucene 2.1 index format (also used for Lucene 2.2).

  • Zend_Search_Lucene::FORMAT_2_3 for Java Lucene 2.3 index format.

Index modifications are performed only if any index update is done. That happens if a new document is added to an index or index optimization is started manually by $index->optimize() call.

In a such case Zend_Search_Lucene may convert index to the higher format version. That always happens for the indices in Zend_Search_Lucene::FORMAT_PRE_2_1 format, which are automatically converted to 2.1 format.

You may manage conversion process and assign target index format by $index->setFormatVersion() which takes Zend_Search_Lucene::FORMAT_2_1 or Zend_Search_Lucene::FORMAT_2_3 constant as a parameter:

  • Zend_Search_Lucene::FORMAT_2_1 actually does nothing since pre-2.1 indices are automatically converted to 2.1 format.

  • Zend_Search_Lucene::FORMAT_2_3 forces conversion to the 2.3 format.

Backward conversions are not supported.

Note: Important!
 Once index is converted to upper version it can't be converted back. So make a backup of your index when you plan migration to upper version, but want to have possibility to go back.

Using the index as static property

The Zend_Search_Lucene object uses the destructor method to commit changes and clean up resources.

It stores added documents in memory and dumps new index segment to disk depending on MaxBufferedDocs parameter.

If MaxBufferedDocs limit is not reached then there are some "unsaved" documents which are saved as a new segment in the object's destructor method. The index auto-optimization procedure is invoked if necessary depending on the values of the MaxBufferedDocs, MaxMergeDocs and MergeFactor parameters.

Static object properties (see below) are destroyed after the last line of the executed script.

  1. class Searcher {
  2.     private static $_index;
  3.
  4.     public static function initIndex() {
  5.         self::$_index = Zend_Search_Lucene::open('path/to/index');
  6.     }
  7. }
  8.
  9. Searcher::initIndex();

All the same, the destructor for static properties is correctly invoked at this point in the program's execution.

One potential problem is exception handling. Exceptions thrown by destructors of static objects don't have context, because the destructor is executed after the script has already completed.

You might see a "Fatal error: Exception thrown without a stack frame in Unknown on line 0" error message instead of exception description in such cases.

Zend_Search_Lucene provides a workaround to this problem with the commit() method. It saves all unsaved changes and frees memory used for storing new segments. You are free to use the commit operation any time- or even several times- during script execution. You can still use the Zend_Search_Lucene object for searching, adding or deleting document after the commit operation. But the commit() call guarantees that if there are no document added or deleted after the call to commit(), then the Zend_Search_Lucene destructor has nothing to do and will not throw exception:

  1. class Searcher {
  2.     private static $_index;
  3.
  4.     public static function initIndex() {
  5.         self::$_index = Zend_Search_Lucene::open('path/to/index');
  6.     }
  7.
  8.     ...
  9.
  10.     public static function commit() {
  11.         self::$_index->commit();
  12.     }
  13. }
  14.
  15. Searcher::initIndex();
  16.
  17. ...
  18.
  19. // Script shutdown routine
  20. ...
  21. Searcher::commit();
  22. ...

与 Java Lucene 的互操作性
Zend_Search_Lucene
Zend Framework手册 中文版
Best Practices
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Search_Lucene
  • 概述
  • 建立索引
  • 搜索索引
  • Query Language
  • 查询类型
  • 字符集
  • 扩展性
  • 与 Java Lucene 的互操作性
  • Advanced
  • Best Practices


Best Practices - Zend Framework Manual

Advanced
Zend_Search_Lucene
Zend Framework手册 中文版
Zend_Serializer

Best Practices

Field names

There are no limitations for field names in Zend_Search_Lucene.

Nevertheless it's a good idea not to use 'id' and 'score' names to avoid ambiguity in QueryHit properties names.

The Zend_Search_Lucene_Search_QueryHit id and score properties always refer to internal Lucene document id and hit score. If the indexed document has the same stored fields, you have to use the getDocument() method to access them:

  1. $hits = $index->find($query);
  2.
  3. foreach ($hits as $hit) {
  4.     // Get 'title' document field
  5.     $title = $hit->title;
  6.
  7.     // Get 'contents' document field
  8.     $contents = $hit->contents;
  9.
  10.     // Get internal Lucene document id
  11.     $id = $hit->id;
  12.
  13.     // Get query hit score
  14.     $score = $hit->score;
  15.
  16.     // Get 'id' document field
  17.     $docId = $hit->getDocument()->id;
  18.
  19.     // Get 'score' document field
  20.     $docId = $hit->getDocument()->score;
  21.
  22.     // Another way to get 'title' document field
  23.     $title = $hit->getDocument()->title;
  24. }

Indexing performance

Indexing performance is a compromise between used resources, indexing time and index quality.

Index quality is completely determined by number of index segments.

Each index segment is entirely independent portion of data. So indexes containing more segments need more memory and time for searching.

Index optimization is a process of merging several segments into a new one. A fully optimized index contains only one segment.

Full index optimization may be performed with the optimize() method:

  1. $index = Zend_Search_Lucene::open($indexPath);
  2.
  3. $index->optimize();

Index optimization works with data streams and doesn't take a lot of memory but does require processor resources and time.

Lucene index segments are not updatable by their nature (the update operation requires the segment file to be completely rewritten). So adding new document(s) to an index always generates a new segment. This, in turn, decreases index quality.

An index auto-optimization process is performed after each segment generation and consists of merging partial segments.

There are three options to control the behavior of auto-optimization (see Index optimization section):

  • MaxBufferedDocs is the number of documents that can be buffered in memory before a new segment is generated and written to the hard drive.

  • MaxMergeDocs is the maximum number of documents merged by auto-optimization process into a new segment.

  • MergeFactor determines how often auto-optimization is performed.

Note: All these options are Zend_Search_Lucene object properties- not index properties. They affect only current Zend_Search_Lucene object behavior and may vary for different scripts.

MaxBufferedDocs doesn't have any effect if you index only one document per script execution. On the other hand, it's very important for batch indexing. Greater values increase indexing performance, but also require more memory.

There is simply no way to calculate the best value for the MaxBufferedDocs parameter because it depends on average document size, the analyzer in use and allowed memory.

A good way to find the right value is to perform several tests with the largest document you expect to be added to the index [1] memory_get_usage() memory_get_peak_usage(). It's a best practice not to use more than a half of the allowed memory.

MaxMergeDocs limits the segment size (in terms of documents). It therefore also limits auto-optimization time by guaranteeing that the addDocument() method is not executed more than a certain number of times. This is very important for interactive applications.

Lowering the MaxMergeDocs parameter also may improve batch indexing performance. Index auto-optimization is an iterative process and is performed from bottom up. Small segments are merged into larger segment, which are in turn merged into even larger segments and so on. Full index optimization is achieved when only one large segment file remains.

Small segments generally decrease index quality. Many small segments may also trigger the "Too many open files" error determined by OS limitations [2] Zend_Search_Lucene.

in general, background index optimization should be performed for interactive indexing mode and MaxMergeDocs shouldn't be too low for batch indexing.

MergeFactor affects auto-optimization frequency. Lower values increase the quality of unoptimized indexes. Larger values increase indexing performance, but also increase the number of merged segments. This again may trigger the "Too many open files" error.

MergeFactor groups index segments by their size:

  1. Not greater than MaxBufferedDocs.

  2. Greater than MaxBufferedDocs, but not greater than MaxBufferedDocs*MergeFactor.

  3. Greater than MaxBufferedDocs*MergeFactor, but not greater than MaxBufferedDocs*MergeFactor*MergeFactor.

  4. ...

Zend_Search_Lucene checks during each addDocument() call to see if merging any segments may move the newly created segment into the next group. If yes, then merging is performed.

So an index with N groups may contain MaxBufferedDocs + (N-1)*MergeFactor segments and contains at least MaxBufferedDocs*MergeFactor(N-1) documents.

This gives good approximation for the number of segments in the index:

NumberOfSegments <= MaxBufferedDocs + MergeFactor*log MergeFactor (NumberOfDocuments/MaxBufferedDocs)

MaxBufferedDocs is determined by allowed memory. This allows for the appropriate merge factor to get a reasonable number of segments.

Tuning the MergeFactor parameter is more effective for batch indexing performance than MaxMergeDocs. But it's also more course-grained. So use the estimation above for tuning MergeFactor, then play with MaxMergeDocs to get best batch indexing performance.

Index during Shut Down

The Zend_Search_Lucene instance performs some work at exit time if any documents were added to the index but not written to a new segment.

It also may trigger an auto-optimization process.

The index object is automatically closed when it, and all returned QueryHit objects, go out of scope.

If index object is stored in global variable than it's closed only at the end of script execution[3] PHP.

PHP exception processing is also shut down at this moment.

It doesn't prevent normal index shutdown process, but may prevent accurate error diagnostic if any error occurs during shutdown.

There are two ways with which you may avoid this problem.

The first is to force going out of scope:

  1. $index = Zend_Search_Lucene::open($indexPath);
  2.
  3. ...
  4.
  5. unset($index);

And the second is to perform a commit operation before the end of script execution:

  1. $index = Zend_Search_Lucene::open($indexPath);
  2.
  3. $index->commit();
This possibility is also described in the "Advanced. Using index as static property" section.

Retrieving documents by unique id

It's a common practice to store some unique document id in the index. Examples include url, path, or database id.

Zend_Search_Lucene provides a termDocs() method for retrieving documents containing specified terms.

This is more efficient than using the find() method:

  1. // Retrieving documents with find() method using a query string
  2. $query = $idFieldName . ':' . $docId;
  3. $hits  = $index->find($query);
  4. foreach ($hits as $hit) {
  5.     $title    = $hit->title;
  6.     $contents = $hit->contents;
  7.     ...
  8. }
  9. ...
  10.
  11. // Retrieving documents with find() method using the query API
  12. $term = new Zend_Search_Lucene_Index_Term($docId, $idFieldName);
  13. $query = new Zend_Search_Lucene_Search_Query_Term($term);
  14. $hits  = $index->find($query);
  15. foreach ($hits as $hit) {
  16.     $title    = $hit->title;
  17.     $contents = $hit->contents;
  18.     ...
  19. }
  20.
  21. ...
  22.
  23. // Retrieving documents with termDocs() method
  24. $term = new Zend_Search_Lucene_Index_Term($docId, $idFieldName);
  25. $docIds  = $index->termDocs($term);
  26. foreach ($docIds as $id) {
  27.     $doc = $index->getDocument($id);
  28.     $title    = $doc->title;
  29.     $contents = $doc->contents;
  30.     ...
  31. }

Memory Usage

Zend_Search_Lucene is a relatively memory-intensive module.

It uses memory to cache some information and optimize searching and indexing performance.

The memory required differs for different modes.

The terms dictionary index is loaded during the search. It's actually each 128th [4] Zend_Search_Lucene API term of the full dictionary.

Thus memory usage is increased if you have a high number of unique terms. This may happen if you use untokenized phrases as a field values or index a large volume of non-text information.

An unoptimized index consists of several segments. It also increases memory usage. Segments are independent, so each segment contains its own terms dictionary and terms dictionary index. If an index consists of N segments it may increase memory usage by N times in worst case. Perform index optimization to merge all segments into one to avoid such memory consumption.

Indexing uses the same memory as searching plus memory for buffering documents. The amount of memory used may be managed with MaxBufferedDocs parameter.

Index optimization (full or partial) uses stream-style data processing and doesn't require a lot of memory.

Encoding

Zend_Search_Lucene works with UTF-8 strings internally. So all strings returned by Zend_Search_Lucene are UTF-8 encoded.

You shouldn't be concerned with encoding if you work with pure ASCII data, but you should be careful if this is not the case.

Wrong encoding may cause error notices at the encoding conversion time or loss of data.

Zend_Search_Lucene offers a wide range of encoding possibilities for indexed documents and parsed queries.

Encoding may be explicitly specified as an optional parameter of field creation methods:

  1. $doc = new Zend_Search_Lucene_Document();
  2. $doc->addField(Zend_Search_Lucene_Field::Text('title',
  3.                                               $title,
  4.                                               'iso-8859-1'));
  5. $doc->addField(Zend_Search_Lucene_Field::UnStored('contents',
  6.                                                   $contents,
  7.                                                   'utf-8'));
This is the best way to avoid ambiguity in the encoding used.

If optional encoding parameter is omitted, then the current locale is used. The current locale may contain character encoding data in addition to the language specification:

  1. setlocale(LC_ALL, 'fr_FR');
  2. ...
  3.
  4. setlocale(LC_ALL, 'de_DE.iso-8859-1');
  5. ...
  6.
  7. setlocale(LC_ALL, 'ru_RU.UTF-8');
  8. ...

The same approach is used to set query string encoding.

If encoding is not specified, then the current locale is used to determine the encoding.

Encoding may be passed as an optional parameter, if the query is parsed explicitly before search:

  1. $query =
  2.     Zend_Search_Lucene_Search_QueryParser::parse($queryStr, 'iso-8859-5');
  3. $hits = $index->find($query);
  4. ...

The default encoding may also be specified with setDefaultEncoding() method:

  1. Zend_Search_Lucene_Search_QueryParser::setDefaultEncoding('iso-8859-1');
  2. $hits = $index->find($queryStr);
  3. ...
The empty string implies 'current locale'.

If the correct encoding is specified it can be correctly processed by analyzer. The actual behavior depends on which analyzer is used. See the Character Set documentation section for details.

Index maintenance

It should be clear that Zend_Search_Lucene as well as any other Lucene implementation does not comprise a "database".

Indexes should not be used for data storage. They do not provide partial backup/restore functionality, journaling, logging, transactions and many other features associated with database management systems.

Nevertheless, Zend_Search_Lucene attempts to keep indexes in a consistent state at all times.

Index backup and restoration should be performed by copying the contents of the index folder.

If index corruption occurs for any reason, the corrupted index should be restored or completely rebuilt.

So it's a good idea to backup large indexes and store changelogs to perform manual restoration and roll-forward operations if necessary. This practice dramatically reduces index restoration time.

[1] and may be used to control memory usage.
[2] keeps each segment file opened to improve search performance.
[3] This also may occur if the index or QueryHit instances are referred to in some cyclical data structures, because garbage collects objects with cyclic references only at the end of script execution.
[4] The Lucene file format allows you to configure this number, but doesn't expose this in its . Nevertheless you still have the ability to configure this value if the index is prepared with another Lucene implementation.
Advanced
Zend_Search_Lucene
Zend Framework手册 中文版
Zend_Serializer
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Search_Lucene
  • 概述
  • 建立索引
  • 搜索索引
  • Query Language
  • 查询类型
  • 字符集
  • 扩展性
  • 与 Java Lucene 的互操作性
  • Advanced
  • Best Practices


Zend_Serializer - Zend Framework Manual

Best Practices
Zend Framework Reference
Zend Framework手册 中文版
Introduction

Zend_Serializer

Table of Contents
  • Introduction
  • Zend_Serializer_Adapter
Best Practices
Zend Framework Reference
Zend Framework手册 中文版
Introduction
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


Introduction - Zend Framework Manual

Zend_Serializer
Zend_Serializer
Zend Framework手册 中文版
Zend_Serializer_Adapter

Introduction

Zend_Serializer provides an adapter based interface to simply generate storable representation of php types by different facilities, and recover.

Example #1 Using Zend_Serializer dynamic interface

To instantiate a serializer you should use the factory method with the name of the adapter:

  1. $serializer = Zend_Serializer::factory('PhpSerialize');
  2. // Now $serializer is an instance of Zend_Serializer_Adapter_AdapterInterface,
  3. // specifically Zend_Serializer_Adapter_PhpSerialize
  4.
  5. try {
  6.     $serialized = $serializer->serialize($data);
  7.     // now $serialized is a string
  8.
  9.     $unserialized = $serializer->unserialize($serialized);
  10.     // now $data == $unserialized
  11. } catch (Zend_Serializer_Exception $e) {
  12.     echo $e;
  13. }

The method serialize generates a storable string. To regenerate this serialized data you can simply call the method unserialize.

Any time an error is encountered serializing or unserializing, Zend_Serializer will throw a Zend_Serializer_Exception.

To configure a given serializer adapter, you can optionally add an array or an instance of Zend_Config to the factory or to the un-/serialize methods:

  1. $serializer = Zend_Serializer::factory('Wddx', array(
  2.     'comment' => 'serialized by Zend_Serializer',
  3. ));
  4.
  5. try {
  6.     $serialized = $serializer->serialize($data, array('comment' => 'change comment'));
  7.     $unserialized = $serializer->unserialize($serialized, array(/* options for unserialize */));
  8. } catch (Zend_Serializer_Exception $e) {
  9.     echo $e;
  10. }

Options passed to the factory are valid for the instantiated object. You can change these options using the setOption(s) method. To change one or more options only for a single call, pass them as the second argument to either the serialize or unserialize method.

Using the Zend_Serializer static interface

You can register a specific serializer adapter as a default serialization adapter for use with Zend_Serializer. By default, the PhpSerialize adapter will be registered, but you can change this option using the setDefaultAdapter() static method.

  1. Zend_Serializer::setDefaultAdapter('PhpSerialize', $options);
  2. // or
  3. $serializer = Zend_Serializer::factory('PhpSerialize', $options);
  4. Zend_Serializer::setDefaultAdapter($serializer);
  5.
  6. try {
  7.     $serialized   = Zend_Serializer::serialize($data, $options);
  8.     $unserialized = Zend_Serializer::unserialize($serialized, $options);
  9. } catch (Zend_Serializer_Exception $e) {
  10.     echo $e;
  11. }
Zend_Serializer
Zend_Serializer
Zend Framework手册 中文版
Zend_Serializer_Adapter
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Serializer
  • Introduction
  • Zend_Serializer_Adapter


Zend_Serializer_Adapter - Zend Framework Manual

Introduction
Zend_Serializer
Zend Framework手册 中文版
Zend_Server

Zend_Serializer_Adapter

Zend_Serializer adapters create a bridge for different methods of serializing with very little effort.

Every adapter has different pros and cons. In some cases, not every PHP datatype (e.g., objects) can be converted to a string representation. In most such cases, the type will be converted to a similar type that is serializable -- as an example, PHP objects will often be cast to arrays. If this fails, a Zend_Serializer_Exception will be thrown.

Below is a list of available adapters.

Zend_Serializer_Adapter_PhpSerialize

This adapter uses the built-in un/serialize PHP functions, and is a good default adapter choice.

There are no configurable options for this adapter.

Zend_Serializer_Adapter_Igbinary

» Igbinary is Open Source Software released by Sulake Dynamoid Oy. It's a drop-in replacement for the standard PHP serializer. Instead of time and space consuming textual representation, igbinary stores PHP data structures in a compact binary form. Savings are significant when using memcached or similar memory based storages for serialized data.

You need the igbinary PHP extension installed on your system in order to use this adapter.

There adapter takes no configuration options.

Zend_Serializer_Adapter_Wddx

» WDDX (Web Distributed Data eXchange) is a programming-language-, platform-, and transport-neutral data interchange mechanism for passing data between different environments and different computers.

The adapter simply uses the » wddx_*() PHP functions. Please read the php manual to determine how you may enable them in your PHP installation.

Additionally, the » SimpleXML PHP extension is used to check if a returned NULL value from wddx_unserialize() is based on a serialized NULL or on invalid data.

Available options include:

Zend_Serializer_Adapter_Wddx Options
Option | Data Type | Default Value | Description
comment | string |  | An optional comment that appears in the packet header.

Zend_Serializer_Adapter_Json

The JSON adapter provides a bridge to the Zend_Json component and/or ext/json. Please read the Zend_Json documentation for further information.

Available options include:

Zend_Serializer_Adapter_Json Options
Option | Data Type | Default Value | Description
cycleCheck | boolean | false | See
objectDecodeType | Zend_Json::TYPE_* | Zend_Json::TYPE_ARRAY | See
enableJsonExprFinder | boolean | false | See

Zend_Serializer_Adapter_Amf 0 and 3

The AMF adapters, Zend_Serializer_Adapter_Amf0 and Zend_Serializer_Adapter_Amf3, provide a bridge to the serializer of the Zend_Amf component. Please read the Zend_Amf documentation for further information.

There are no options for these adapters.

Zend_Serializer_Adapter_PythonPickle

This adapter converts PHP types to a » Python Pickle string representation. With it, you can read the serialized data with Python and read Pickled data of Python with PHP.

Available options include:

Zend_Serializer_Adapter_PythonPickle Options
Option | Data Type | Default Value | Description
protocol | integer (0 | 1 | 2 | 3) | 0 | The Pickle protocol version used on serialize

Datatype merging (PHP to Python) occurs as follows:

Datatype merging (PHP to Python)
PHP Type | Python Type
NULL | None
boolean | boolean
integer | integer
float | float
string | string
array | list
associative array | dictionary
object | dictionary

Datatype merging (Python to PHP) occurs per the following:

Datatype merging (Python to PHP)
Python-Type | PHP-Type
None | NULL
boolean | boolean
integer | integer
long | integer | float | string | Zend_Serializer_Exception
float | float
string | string
bytes | string
Unicode string | UTF-8 string
list | array
tuple | array
dictionary | associative array
All other types | Zend_Serializer_Exception

Zend_Serializer_Adapter_PhpCode

This adapter generates a parsable PHP code representation using » var_export(). On restoring, the data will be executed using » eval.

There are no configuration options for this adapter.

Warning

Unserializing objects

Objects will be serialized using the » __set_state magic method. If the class doesn't implement this method, a fatal error will occur during execution.

Warning

Uses eval()

The PhpCode adapter utilizes eval() to unserialize. This introduces both a performance and potential security issue as a new process will be executed. Typically, you should use the PhpSerialize adapter unless you require human-readability of the serialized data.

Introduction
Zend_Serializer
Zend Framework手册 中文版
Zend_Server
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Serializer
  • Introduction
  • Zend_Serializer_Adapter


Zend_Server - Zend Framework Manual

Zend_Serializer_Adapter
Zend Framework Reference
Zend Framework手册 中文版
简介

Zend_Server

Table of Contents
  • 简介
  • Zend_Server_Reflection
Zend_Serializer_Adapter
Zend Framework Reference
Zend Framework手册 中文版
简介
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


简介 - Zend Framework Manual

Zend_Server
Zend_Server
Zend Framework手册 中文版
Zend_Server_Reflection

简介

Zend_Server 类家族为各种各样的服务器类提供功能，包括 Zend_XmlRpc_Server、 Zend_Rest_Server、Zend_Json_Server 和 Zend_Soap_Wsdl。Zend_Server_Interface 提供了一个模仿 PHP 5 的 SoapServer 类的接口；为了提供标准的服务器 API，所有的服务器类应该实现这个接口。

Zend_Server_Reflection 树提供了一个标准机制，在这个机制下，执行函数和类子定义（ introspection )被用做和服务器类一起的回调（callback）；也提供了适合与 Zend_Server_Interface 的 getFunctions() 和 loadFunctions() 方法一起使用的数据。

Zend_Server
Zend_Server
Zend Framework手册 中文版
Zend_Server_Reflection
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Server
  • 简介
  • Zend_Server_Reflection


Zend_Server_Reflection - Zend Framework Manual

简介
Zend_Server
Zend Framework手册 中文版
Zend_Service

Zend_Server_Reflection

简介

Zend_Server_Reflection 提供了一个标准机制，在这个机制下，和服务器类一起执行函数和类自定义（ introspection ），它基于 PHP 5 的 Reflection API，并且集成它来提供方法来获取参数和返回值类型和描述、函数和方法原型的全部列表（例如，所有可能的有效调用组合）和函数/方法描述。

典型地，这个函数将只给框架服务器类的开发者使用。

用法

基本用法很简单：

<?php
require_once 'Zend/Server/Reflection.php';
$class    = Zend_Server_Reflection::reflectClass('My_Class');
$function = Zend_Server_Reflection::reflectFunction('my_function');

// Get prototypes
$prototypes = $reflection->getPrototypes();

// Loop through each prototype for the function
foreach ($prototypes as $prototype) {

    // Get prototype return type
    echo "Return type: ", $prototype->getReturnType(), "\n";

    // Get prototype parameters
    $parameters = $prototype->getParameters();

    echo "Parameters: \n";
    foreach ($parameters as $parameter) {
        // Get parameter type
        echo "    ", $parameter->getType(), "\n";
    }
}

// Get namespace for a class, function, or method.
// Namespaces may be set at instantiation time (second argument), or using
// setNamespace()
$reflection->getNamespace();

reflectFunction() 返回一个 Zend_Server_Reflection_Function 对象；reflectClass 返回一个 Zend_Server_Reflection_Class 对象。请参考 API 文档来获知那些方法有用。

简介
Zend_Server
Zend Framework手册 中文版
Zend_Service
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Server
  • 简介
  • Zend_Server_Reflection


Zend_Service - Zend Framework Manual

Zend_Server_Reflection
Zend Framework Reference
Zend Framework手册 中文版
简介

Zend_Service

Table of Contents
  • 简介
  • Zend_Service_Akismet
  • Zend_Service_Amazon
  • Zend_Service_Amazon_Ec2
  • Zend_Service_Amazon_Ec2: Instances
  • Zend_Service_Amazon_Ec2: Windows Instances
  • Zend_Service_Amazon_Ec2: Reserved Instances
  • Zend_Service_Amazon_Ec2: CloudWatch Monitoring
  • Zend_Service_Amazon_Ec2: Amazon Machine Images (AMI)
  • Zend_Service_Amazon_Ec2: Elastic Block Stroage (EBS)
  • Zend_Service_Amazon_Ec2: Elastic IP Addresses
  • Zend_Service_Amazon_Ec2: Keypairs
  • Zend_Service_Amazon_Ec2: Regions and Availability Zones
  • Zend_Service_Amazon_Ec2: Security Groups
  • Zend_Service_Amazon_S3
  • Zend_Service_Amazon_Sqs
  • Zend_Service_Audioscrobbler
  • Zend_Service_Delicious
  • Zend_Service_DeveloperGarden
  • Zend_Service_Flickr
  • Zend_Service_LiveDocx
  • Zend_Service_Nirvanix
  • Zend_Service_ReCaptcha
  • Zend_Service_Simpy
  • Introduction
  • Zend_Service_StrikeIron
  • Zend_Service_StrikeIron: Bundled Services
  • Zend_Service_StrikeIron: Advanced Uses
  • Zend_Service_Technorati
  • Zend_Service_Twitter
  • Zend_Service_WindowsAzure
  • Zend_Service_Yahoo
Zend_Server_Reflection
Zend Framework Reference
Zend Framework手册 中文版
简介
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


简介 - Zend Framework Manual

Zend_Service
Zend_Service
Zend Framework手册 中文版
Zend_Service_Akismet

简介

Zend_Service 是一个抽象类，Zend用它来作为实现web service（如：XML-RPC）的基础。 .

通过Zend_Service_Rest类, Zend_Service可以支持任何基于REST的web服务。 .

除了可以扩展 Zend_Service 并对基于REST的web services使用 Zend_Service_Rest 类进行操作之外，Zend也同时提供对流行的web services的支持，如 Amazon, Flickr, 和 Yahoo!. 而且也许不久会加入更多的web serivces哦．

Zend_Service
Zend_Service
Zend Framework手册 中文版
Zend_Service_Akismet
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Service
  • 简介
  • Zend_Service_Akismet
  • Zend_Service_Amazon
  • Zend_Service_Amazon_Ec2
  • Zend_Service_Amazon_Ec2: Instances
  • Zend_Service_Amazon_Ec2: Windows Instances
  • Zend_Service_Amazon_Ec2: Reserved Instances
  • Zend_Service_Amazon_Ec2: CloudWatch Monitoring
  • Zend_Service_Amazon_Ec2: Amazon Machine Images (AMI)
  • Zend_Service_Amazon_Ec2: Elastic Block Stroage (EBS)
  • Zend_Service_Amazon_Ec2: Elastic IP Addresses
  • Zend_Service_Amazon_Ec2: Keypairs
  • Zend_Service_Amazon_Ec2: Regions and Availability Zones
  • Zend_Service_Amazon_Ec2: Security Groups
  • Zend_Service_Amazon_S3
  • Zend_Service_Amazon_Sqs
  • Zend_Service_Audioscrobbler
  • Zend_Service_Delicious
  • Zend_Service_DeveloperGarden
  • Zend_Service_Flickr
  • Zend_Service_LiveDocx
  • Zend_Service_Nirvanix
  • Zend_Service_ReCaptcha
  • Zend_Service_Simpy
  • Introduction
  • Zend_Service_StrikeIron
  • Zend_Service_StrikeIron: Bundled Services
  • Zend_Service_StrikeIron: Advanced Uses
  • Zend_Service_Technorati
  • Zend_Service_Twitter
  • Zend_Service_WindowsAzure
  • Zend_Service_Yahoo


Zend_Service_Akismet - Zend Framework Manual

简介
Zend_Service
Zend Framework手册 中文版
Zend_Service_Amazon

Zend_Service_Akismet

Introduction

Zend_Service_Akismet provides a client for the » Akismet API. The Akismet service is used to determine if incoming data is potentially spam. It also exposes methods for submitting data as known spam or as false positives (ham). It was originally intended to help categorize and identify spam for Wordpress, but it can be used for any type of data.

Akismet requires an API key for usage. You can get one by signing up for a » WordPress.com account. You do not need to activate a blog. Simply acquiring the account will provide you with the API key.

Akismet requires that all requests contain a URL to the resource for which data is being filtered. Because of Akismet's origins in WordPress, this resource is called the blog URL. This value should be passed as the second argument to the constructor, but may be reset at any time using the setBlogUrl() method, or overridden by specifying a 'blog' key in the various method calls.

Verify an API key

Zend_Service_Akismet::verifyKey($key) is used to verify that an Akismet API key is valid. In most cases, you will not need to check, but if you need a sanity check, or to determine if a newly acquired key is active, you may do so with this method.

  1. // Instantiate with the API key and a URL to the application or
  2. // resource being used
  3. $akismet = new Zend_Service_Akismet($apiKey,
  4.                                     'http://framework.zend.com/wiki/');
  5. if ($akismet->verifyKey($apiKey) {
  6.     echo "Key is valid.\n";
  7. } else {
  8.     echo "Key is not valid\n";
  9. }

If called with no arguments, verifyKey() uses the API key provided to the constructor.

verifyKey() implements Akismet's verify-key REST method.

Check for spam

Zend_Service_Akismet::isSpam($data) is used to determine if the data provided is considered spam by Akismet. It accepts an associative array as the sole argument. That array requires the following keys be set:

  • user_ip, the IP address of the user submitting the data (not your IP address, but that of a user on your site).

  • user_agent, the reported UserAgent string (browser and version) of the user submitting the data.

The following keys are also recognized specifically by the API:

  • blog, the fully qualified URL to the resource or application. If not specified, the URL provided to the constructor will be used.

  • referrer, the content of the HTTP_REFERER header at the time of submission. (Note spelling; it does not follow the header name.)

  • permalink, the permalink location, if any, of the entry the data was submitted to.

  • comment_type, the type of data provided. Values specified in the API include 'comment', 'trackback', 'pingback', and an empty string (''), but it may be any value.

  • comment_author, the name of the person submitting the data.

  • comment_author_email, the email of the person submitting the data.

  • comment_author_url, the URL or home page of the person submitting the data.

  • comment_content, the actual data content submitted.

You may also submit any other environmental variables you feel might be a factor in determining if data is spam. Akismet suggests the contents of the entire $_SERVER array.

The isSpam() method will return either TRUE or FALSE, or throw an exception if the API key is invalid.

Example #1 isSpam() Usage

  1. $data = array(
  2.     'user_ip'              => '111.222.111.222',
  3.     'user_agent'           => 'Mozilla/5.0 ' . (Windows; U; Windows NT ' .
  4.                               '5.2; en-GB; rv:1.8.1) Gecko/20061010 ' .
  5.                               'Firefox/2.0',
  6.     'comment_type'         => 'contact',
  7.     'comment_author'       => 'John Doe',
  8.     'comment_author_email' => 'nospam@myhaus.net',
  9.     'comment_content'      => "I'm not a spammer, honest!"
  10. );
  11. if ($akismet->isSpam($data)) {
  12.     echo "Sorry, but we think you're a spammer.";
  13. } else {
  14.     echo "Welcome to our site!";
  15. }

isSpam() implements the comment-check Akismet API method.

Submitting known spam

Spam data will occasionally get through the filter. If you discover spam that you feel should have been caught, you can submit it to Akismet to help improve their filter.

Zend_Service_Akismet::submitSpam() takes the same data array as passed to isSpam(), but does not return a value. An exception will be raised if the API key used is invalid.

Example #2 submitSpam() Usage

  1. $data = array(
  2.     'user_ip'              => '111.222.111.222',
  3.     'user_agent'           => 'Mozilla/5.0 (Windows; U; Windows NT 5.2;' .
  4.                               'en-GB; rv:1.8.1) Gecko/20061010 Firefox/2.0',
  5.     'comment_type'         => 'contact',
  6.     'comment_author'       => 'John Doe',
  7.     'comment_author_email' => 'nospam@myhaus.net',
  8.     'comment_content'      => "I'm not a spammer, honest!"
  9. );
  10. $akismet->submitSpam($data));

submitSpam() implements the submit-spam Akismet API method.

Submitting false positives (ham)

Data will occasionally be trapped erroneously as spam by Akismet. For this reason, you should probably keep a log of all data trapped as spam by Akismet and review it periodically. If you find such occurrences, you can submit the data to Akismet as "ham", or a false positive (ham is good, spam is not).

 Zend_Service_Akismet::submitHam() takes the same data
array as passed to  isSpam() or
 submitSpam(), and, like  submitSpam(), does
not return a value. An exception will be raised if the API key used
is invalid.

Example #3 submitHam() Usage

  1. $data = array(
  2.     'user_ip'              => '111.222.111.222',
  3.     'user_agent'           => 'Mozilla/5.0 (Windows; U; Windows NT 5.2;' .
  4.                               'en-GB; rv:1.8.1) Gecko/20061010 Firefox/2.0',
  5.     'comment_type'         => 'contact',
  6.     'comment_author'       => 'John Doe',
  7.     'comment_author_email' => 'nospam@myhaus.net',
  8.     'comment_content'      => "I'm not a spammer, honest!"
  9. );
  10. $akismet->submitHam($data));

submitHam() implements the submit-ham Akismet API method.

Zend-specific Methods

While the Akismet API only specifies four methods, Zend_Service_Akismet has several additional methods that may be used for retrieving and modifying internal properties.

  • getBlogUrl() and setBlogUrl() allow you to retrieve and modify the blog URL used in requests.

  • getApiKey() and setApiKey() allow you to retrieve and modify the API key used in requests.

  • getCharset() and setCharset() allow you to retrieve and modify the character set used to make the request.

  • getPort() and setPort() allow you to retrieve and modify the TCP port used to make the request.

  • getUserAgent() and setUserAgent() allow you to retrieve and modify the HTTP user agent used to make the request. Note: this is not the user_agent used in data submitted to the service, but rather the value provided in the HTTP User-Agent header when making a request to the service.

    The value used to set the user agent should be of the form some user agent/version | Akismet/version. The default is Zend Framework/ZF-VERSION | Akismet/1.11, where ZF-VERSION is the current Zend Framework version as stored in the Zend_Framework::VERSION constant.

简介
Zend_Service
Zend Framework手册 中文版
Zend_Service_Amazon
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Service
  • 简介
  • Zend_Service_Akismet
  • Zend_Service_Amazon
  • Zend_Service_Amazon_Ec2
  • Zend_Service_Amazon_Ec2: Instances
  • Zend_Service_Amazon_Ec2: Windows Instances
  • Zend_Service_Amazon_Ec2: Reserved Instances
  • Zend_Service_Amazon_Ec2: CloudWatch Monitoring
  • Zend_Service_Amazon_Ec2: Amazon Machine Images (AMI)
  • Zend_Service_Amazon_Ec2: Elastic Block Stroage (EBS)
  • Zend_Service_Amazon_Ec2: Elastic IP Addresses
  • Zend_Service_Amazon_Ec2: Keypairs
  • Zend_Service_Amazon_Ec2: Regions and Availability Zones
  • Zend_Service_Amazon_Ec2: Security Groups
  • Zend_Service_Amazon_S3
  • Zend_Service_Amazon_Sqs
  • Zend_Service_Audioscrobbler
  • Zend_Service_Delicious
  • Zend_Service_DeveloperGarden
  • Zend_Service_Flickr
  • Zend_Service_LiveDocx
  • Zend_Service_Nirvanix
  • Zend_Service_ReCaptcha
  • Zend_Service_Simpy
  • Introduction
  • Zend_Service_StrikeIron
  • Zend_Service_StrikeIron: Bundled Services
  • Zend_Service_StrikeIron: Advanced Uses
  • Zend_Service_Technorati
  • Zend_Service_Twitter
  • Zend_Service_WindowsAzure
  • Zend_Service_Yahoo


Zend_Service_Amazon - Zend Framework Manual

Zend_Service_Akismet
Zend_Service
Zend Framework手册 中文版
Zend_Service_Amazon_Ec2

Zend_Service_Amazon

Introduction

Zend_Service_Amazon is a simple API for using Amazon web services. Zend_Service_Amazon has two APIs: a more traditional one that follows Amazon's own API, and a simpler "Query API" for constructing even complex search queries easily.

Zend_Service_Amazon enables developers to retrieve information appearing throughout Amazon.com web sites directly through the Amazon Web Services API. Examples include:

  • Store item information, such as images, descriptions, pricing, and more

  • Customer and editorial reviews

  • Similar products and accessories

  • Amazon.com offers

  • ListMania lists

In order to use Zend_Service_Amazon, you should already have an Amazon developer API key aswell as a secret key. To get a key and for more information, please visit the » Amazon Web Services web site. As of August 15th, 2009 you can only use the Amazon Product Advertising API through Zend_Service_Amazon, when specifying the additional secret key.

Note: Attention
 Your Amazon developer API and secret keys are linked to your Amazon identity, so take appropriate measures to keep them private.

Example #1 Search Amazon Using the Traditional API

In this example, we search for PHP books at Amazon and loop through the results, printing them.

  1. $amazon = new Zend_Service_Amazon('AMAZON_API_KEY', 'US', 'AMAZON_SECRET_KEY');
  2. $results = $amazon->itemSearch(array('SearchIndex' => 'Books',
  3.                                      'Keywords' => 'php'));
  4. foreach ($results as $result) {
  5.     echo $result->Title . '<br />';
  6. }

Example #2 Search Amazon Using the Query API

Here, we also search for PHP books at Amazon, but we instead use the Query API, which resembles the Fluent Interface design pattern.

  1. $query = new Zend_Service_Amazon_Query('AMAZON_API_KEY',
  2.                                        'US',
  3.                                        'AMAZON_SECRET_KEY');
  4. $query->category('Books')->Keywords('PHP');
  5. $results = $query->search();
  6. foreach ($results as $result) {
  7.     echo $result->Title . '<br />';
  8. }

Country Codes

By default, Zend_Service_Amazon connects to the United States ("US") Amazon web service. To connect from a different country, simply specify the appropriate country code string as the second parameter to the constructor:

Example #3 Choosing an Amazon Web Service Country

  1. // Connect to Amazon in Japan
  2. $amazon = new Zend_Service_Amazon('AMAZON_API_KEY', 'JP', 'AMAZON_SECRET_KEY');

Note: Country codes
 Valid country codes are: CA, DE, FR, JP, UK, and US.

Looking up a Specific Amazon Item by ASIN

The itemLookup() method provides the ability to fetch a particular Amazon item when the ASIN is known.

Example #4 Looking up a Specific Amazon Item by ASIN

  1. $amazon = new Zend_Service_Amazon('AMAZON_API_KEY', 'US', 'AMAZON_SECRET_KEY');
  2. $item = $amazon->itemLookup('B0000A432X');

The itemLookup() method also accepts an optional second parameter for handling search options. For full details, including a list of available options, please see the » relevant Amazon documentation.

Note: Image information
 To retrieve images information for your search results, you must set ResponseGroup option to Medium or Large.

Performing Amazon Item Searches

Searching for items based on any of various available criteria are made simple using the itemSearch() method, as in the following example:

Example #5 Performing Amazon Item Searches

  1. $amazon = new Zend_Service_Amazon('AMAZON_API_KEY', 'US', 'AMAZON_SECRET_KEY');
  2. $results = $amazon->itemSearch(array('SearchIndex' => 'Books',
  3.                                      'Keywords' => 'php'));
  4. foreach ($results as $result) {
  5.     echo $result->Title . '<br />';
  6. }

Example #6 Using the ResponseGroup Option

The ResponseGroup option is used to control the specific information that will be returned in the response.

  1. $amazon = new Zend_Service_Amazon('AMAZON_API_KEY', 'US', 'AMAZON_SECRET_KEY');
  2. $results = $amazon->itemSearch(array(
  3.     'SearchIndex'   => 'Books',
  4.     'Keywords'      => 'php',
  5.     'ResponseGroup' => 'Small,ItemAttributes,Images,SalesRank,Reviews,' .
  6.                        'EditorialReview,Similarities,ListmaniaLists'
  7.     ));
  8. foreach ($results as $result) {
  9.     echo $result->Title . '<br />';
  10. }

The itemSearch() method accepts a single array parameter for handling search options. For full details, including a list of available options, please see the » relevant Amazon documentation

Tip

The Zend_Service_Amazon_Query class is an easy to use wrapper around this method.

Using the Alternative Query API

Introduction

Zend_Service_Amazon_Query provides an alternative API for using the Amazon Web Service. The alternative API uses the Fluent Interface pattern. That is, all calls can be made using chained method calls. (e.g., $obj->method()->method2($arg))

The Zend_Service_Amazon_Query API uses overloading to easily set up an item search and then allows you to search based upon the criteria specified. Each of the options is provided as a method call, and each method's argument corresponds to the named option's value:

Example #7 Search Amazon Using the Alternative Query API

In this example, the alternative query API is used as a fluent interface to specify options and their respective values:

  1. $query = new Zend_Service_Amazon_Query('MY_API_KEY', 'US', 'AMAZON_SECRET_KEY');
  2. $query->Category('Books')->Keywords('PHP');
  3. $results = $query->search();
  4. foreach ($results as $result) {
  5.     echo $result->Title . '<br />';
  6. }

This sets the option Category to "Books" and Keywords to "PHP".

For more information on the available options, please refer to the » relevant Amazon documentation.

Zend_Service_Amazon Classes

The following classes are all returned by Zend_Service_Amazon::itemLookup() and Zend_Service_Amazon::itemSearch():

  • Zend_Service_Amazon_Item

  • Zend_Service_Amazon_Image

  • Zend_Service_Amazon_ResultSet

  • Zend_Service_Amazon_OfferSet

  • Zend_Service_Amazon_Offer

  • Zend_Service_Amazon_SimilarProduct

  • Zend_Service_Amazon_Accessories

  • Zend_Service_Amazon_CustomerReview

  • Zend_Service_Amazon_EditorialReview

  • Zend_Service_Amazon_ListMania

Zend_Service_Amazon_Item

Zend_Service_Amazon_Item is the class type used to represent an Amazon item returned by the web service. It encompasses all of the items attributes, including title, description, reviews, etc.

Zend_Service_Amazon_Item::asXML()

string asXML ( void )

Return the original XML for the item

Properties

Zend_Service_Amazon_Item has a number of properties directly related to their standard Amazon API counterparts.

Zend_Service_Amazon_Item Properties
Name | Type | Description
ASIN | string | Amazon Item ID
DetailPageURL | string | URL to the Items Details Page
SalesRank | int | Sales Rank for the Item
SmallImage | Zend_Service_Amazon_Image | Small Image of the Item
MediumImage | Zend_Service_Amazon_Image | Medium Image of the Item
LargeImage | Zend_Service_Amazon_Image | Large Image of the Item
Subjects | array | Item Subjects
Offers | Zend_Service_Amazon_OfferSet | Offer Summary and Offers for the Item
CustomerReviews | array | Customer reviews represented as an array of Zend_Service_Amazon_CustomerReview objects
EditorialReviews | array | Editorial reviews represented as an array of Zend_Service_Amazon_EditorialReview objects
SimilarProducts | array | Similar Products represented as an array of Zend_Service_Amazon_SimilarProduct objects
Accessories | array | Accessories for the item represented as an array of Zend_Service_Amazon_Accessories objects
Tracks | array | An array of track numbers and names for Music CDs and DVDs
ListmaniaLists | array | Item related Listmania Lists as an array of Zend_Service_Amazon_ListmainList objects
PromotionalTag | string | Item Promotional Tag

Back to Class List

Zend_Service_Amazon_Image

Zend_Service_Amazon_Image represents a remote Image for a product.

Properties

Zend_Service_Amazon_Image Properties
Name | Type | Description
Url | Zend_Uri | Remote URL for the Image
Height | int | The Height of the image in pixels
Width | int | The Width of the image in pixels

Back to Class List

Zend_Service_Amazon_ResultSet

Zend_Service_Amazon_ResultSet objects are returned by Zend_Service_Amazon::itemSearch() and allow you to easily handle the multiple results returned.

Note: SeekableIterator
 Implements the SeekableIterator for easy iteration (e.g. using foreach), as well as direct access to a specific result using seek().

Zend_Service_Amazon_ResultSet::totalResults()

int totalResults ( void )

Returns the total number of results returned by the search

Back to Class List

Zend_Service_Amazon_OfferSet

Each result returned by Zend_Service_Amazon::itemSearch() and Zend_Service_Amazon::itemLookup() contains a Zend_Service_Amazon_OfferSet object through which pricing information for the item can be retrieved.

Properties

Zend_Service_Amazon_OfferSet Properties
Name | Type | Description
LowestNewPrice | int | Lowest Price for the item in "New" condition
LowestNewPriceCurrency | string | The currency for the LowestNewPrice
LowestOldPrice | int | Lowest Price for the item in "Used" condition
LowestOldPriceCurrency | string | The currency for the LowestOldPrice
TotalNew | int | Total number of "new" condition available for the item
TotalUsed | int | Total number of "used" condition available for the item
TotalCollectible | int | Total number of "collectible" condition available for the item
TotalRefurbished | int | Total number of "refurbished" condition available for the item
Offers | array | An array of Zend_Service_Amazon_Offer objects.

Back to Class List

Zend_Service_Amazon_Offer

Each offer for an item is returned as an Zend_Service_Amazon_Offer object.

Zend_Service_Amazon_Offer Properties

Properties
Name | Type | Description
MerchantId | string | Merchants Amazon ID
GlancePage | string | URL for a page with a summary of the Merchant
Condition | string | Condition of the item
OfferListingId | string | ID of the Offer Listing
Price | int | Price for the item
CurrencyCode | string | Currency Code for the price of the item
Availability | string | Availability of the item
IsEligibleForSuperSaverShipping | boolean | Whether the item is eligible for Super Saver Shipping or not

Back to Class List

Zend_Service_Amazon_SimilarProduct

When searching for items, Amazon also returns a list of similar products that the searcher may find to their liking. Each of these is returned as a Zend_Service_Amazon_SimilarProduct object.

Each object contains the information to allow you to make sub-sequent requests to get the full information on the item.

Properties

Zend_Service_Amazon_SimilarProduct Properties
Name | Type | Description
ASIN | string | Products Amazon Unique ID (ASIN)
Title | string | Products Title

Back to Class List

Zend_Service_Amazon_Accessories

Accessories for the returned item are represented as Zend_Service_Amazon_Accessories objects

Properties

Zend_Service_Amazon_Accessories Properties
Name | Type | Description
ASIN | string | Products Amazon Unique ID (ASIN)
Title | string | Products Title

Back to Class List

Zend_Service_Amazon_CustomerReview

Each Customer Review is returned as a Zend_Service_Amazon_CustomerReview object.

Properties

Zend_Service_Amazon_CustomerReview Properties
Name | Type | Description
Rating | string | Item Rating
HelpfulVotes | string | Votes on how helpful the review is
CustomerId | string | Customer ID
TotalVotes | string | Total Votes
Date | string | Date of the Review
Summary | string | Review Summary
Content | string | Review Content

Back to Class List

Zend_Service_Amazon_EditorialReview

Each items Editorial Reviews are returned as a Zend_Service_Amazon_EditorialReview object

Properties

Zend_Service_Amazon_EditorialReview Properties
Name | Type | Description
Source | string | Source of the Editorial Review
Content | string | Review Content

Back to Class List

Zend_Service_Amazon_Listmania

Each results List Mania List items are returned as Zend_Service_Amazon_Listmania objects.

Properties

Zend_Service_Amazon_Listmania Properties
Name | Type | Description
ListId | string | List ID
ListName | string | List Name

Back to Class List

Zend_Service_Akismet
Zend_Service
Zend Framework手册 中文版
Zend_Service_Amazon_Ec2
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Service
  • 简介
  • Zend_Service_Akismet
  • Zend_Service_Amazon
  • Zend_Service_Amazon_Ec2
  • Zend_Service_Amazon_Ec2: Instances
  • Zend_Service_Amazon_Ec2: Windows Instances
  • Zend_Service_Amazon_Ec2: Reserved Instances
  • Zend_Service_Amazon_Ec2: CloudWatch Monitoring
  • Zend_Service_Amazon_Ec2: Amazon Machine Images (AMI)
  • Zend_Service_Amazon_Ec2: Elastic Block Stroage (EBS)
  • Zend_Service_Amazon_Ec2: Elastic IP Addresses
  • Zend_Service_Amazon_Ec2: Keypairs
  • Zend_Service_Amazon_Ec2: Regions and Availability Zones
  • Zend_Service_Amazon_Ec2: Security Groups
  • Zend_Service_Amazon_S3
  • Zend_Service_Amazon_Sqs
  • Zend_Service_Audioscrobbler
  • Zend_Service_Delicious
  • Zend_Service_DeveloperGarden
  • Zend_Service_Flickr
  • Zend_Service_LiveDocx
  • Zend_Service_Nirvanix
  • Zend_Service_ReCaptcha
  • Zend_Service_Simpy
  • Introduction
  • Zend_Service_StrikeIron
  • Zend_Service_StrikeIron: Bundled Services
  • Zend_Service_StrikeIron: Advanced Uses
  • Zend_Service_Technorati
  • Zend_Service_Twitter
  • Zend_Service_WindowsAzure
  • Zend_Service_Yahoo


Zend_Service_Amazon_Ec2 - Zend Framework Manual

Zend_Service_Amazon
Zend_Service
Zend Framework手册 中文版
Zend_Service_Amazon_Ec2: Instances

Zend_Service_Amazon_Ec2

Introduction

Zend_Service_Amazon_Ec2 provides an interface to Amazon Elastic Clound Computing (EC2).

What is Amazon Ec2?

Amazon EC2 is a web service that enables you to launch and manage server instances in Amazon's data centers using APIs or available tools and utilities. You can use Amazon EC2 server instances at any time, for as long as you need, and for any legal purpose.

Static Methods

To make using the Ec2 class easier to use there are two static methods that can be invoked from any of the Ec2 Elements. The first static method is setKeys which will defind you AWS Access Keys as default keys. When you then create any new object you don't need to pass in any keys to the constructor.

Example #1 setKeys() Example

  1. Zend_Service_Amazon_Ec2_Ebs::setKeys('aws_key','aws_secret_key');

To set the region that you are working in you can call the setRegion to set which Amazon Ec2 Region you are working in. Currently there is only two region available us-east-1 and eu-west-1. If an invalid value is passed it will throw an exception stating that.

Example #2 setRegion() Example

  1. Zend_Service_Amazon_Ec2_Ebs::setRegion('us-east-1');

Note: Set Amazon Ec2 Region
 Alternativly you can set the region when you create each class as the third parameter in the constructor method.

Zend_Service_Amazon
Zend_Service
Zend Framework手册 中文版
Zend_Service_Amazon_Ec2: Instances
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Service
  • 简介
  • Zend_Service_Akismet
  • Zend_Service_Amazon
  • Zend_Service_Amazon_Ec2
  • Zend_Service_Amazon_Ec2: Instances
  • Zend_Service_Amazon_Ec2: Windows Instances
  • Zend_Service_Amazon_Ec2: Reserved Instances
  • Zend_Service_Amazon_Ec2: CloudWatch Monitoring
  • Zend_Service_Amazon_Ec2: Amazon Machine Images (AMI)
  • Zend_Service_Amazon_Ec2: Elastic Block Stroage (EBS)
  • Zend_Service_Amazon_Ec2: Elastic IP Addresses
  • Zend_Service_Amazon_Ec2: Keypairs
  • Zend_Service_Amazon_Ec2: Regions and Availability Zones
  • Zend_Service_Amazon_Ec2: Security Groups
  • Zend_Service_Amazon_S3
  • Zend_Service_Amazon_Sqs
  • Zend_Service_Audioscrobbler
  • Zend_Service_Delicious
  • Zend_Service_DeveloperGarden
  • Zend_Service_Flickr
  • Zend_Service_LiveDocx
  • Zend_Service_Nirvanix
  • Zend_Service_ReCaptcha
  • Zend_Service_Simpy
  • Introduction
  • Zend_Service_StrikeIron
  • Zend_Service_StrikeIron: Bundled Services
  • Zend_Service_StrikeIron: Advanced Uses
  • Zend_Service_Technorati
  • Zend_Service_Twitter
  • Zend_Service_WindowsAzure
  • Zend_Service_Yahoo


Zend_Service_Amazon_Ec2: CloudWatch Monitoring - Zend Framework Manual

Zend_Service_Amazon_Ec2: Reserved Instances
Zend_Service
Zend Framework手册 中文版
Zend_Service_Amazon_Ec2: Amazon Machine Images (AMI)

Zend_Service_Amazon_Ec2: CloudWatch Monitoring

Amazon CloudWatch is an easy-to-use web service that provides comprehensive monitoring for Amazon Elastic Compute Cloud (Amazon EC2) and Elastic Load Balancing. For more details information check cout the » Amazon CloudWatch Developers Guide

CloudWatch Usage

Example #1 Listing Aviable Metrics

listMetrics() returns a list of up to 500 valid metrics for which there is recorded data available to a you and a NextToken string that can be used to query for the next set of results.

  1. $ec2_ebs = new Zend_Service_Amazon_Ec2_CloudWatch('aws_key','aws_secret_key');
  2. $return = $ec2_ebs->listMetrics();

Example #2 Return Statistics for a given metric

getMetricStatistics() Returns data for one or more statistics of given a metric.

Note: The maximum number of datapoints that the Amazon CloudWatch service will return in a single GetMetricStatistics request is 1,440. If a request is made that would generate more datapoints than this amount, Amazon CloudWatch will return an error. You can alter your request by narrowing the time range (StartTime, EndTime) or increasing the Period in your single request. You may also get all of the data at the granularity you originally asked for by making multiple requests with adjacent time ranges.

getMetricStatistics() only requires two parameters but it also has four additional parameters that are optional.

  • Required:

  • MeasureName The measure name that corresponds to the measure for the gathered metric. Valid EC2 Values are CPUUtilization, NetworkIn, NetworkOut, DiskWriteOps DiskReadBytes, DiskReadOps, DiskWriteBytes. Valid Elastic Load Balancing Metrics are Latency, RequestCount, HealthyHostCount UnHealthyHostCount. » For more information click here

  • Statistics The statistics to be returned for the given metric. Valid values are Average, Maximum, Minimum, Samples, Sum. You can specify this as a string or as an array of values. If you don't specify one it will default to Average instead of failing out. If you specify an incorrect option it will just skip it. » For more information click here

  • Optional:

  • Dimensions Amazon CloudWatch allows you to specify one Dimension to further filter metric data on. If you don't specify a dimension, the service returns the aggregate of all the measures with the given measure name and time range.

  • Unit The standard unit of Measurement for a given Measure. Valid Values: Seconds, Percent, Bytes, Bits, Count, Bytes/Second, Bits/Second, Count/Second, and None. Constraints: When using count/second as the unit, you should use Sum as the statistic instead of Average. Otherwise, the sample returns as equal to the number of requests instead of the number of 60-second intervals. This will cause the Average to always equals one when the unit is count/second.

  • StartTime The timestamp of the first datapoint to return, inclusive. For example, 2008-02-26T19:00:00+00:00. We round your value down to the nearest minute. You can set your start time for more than two weeks in the past. However, you will only get data for the past two weeks. (in ISO 8601 format). Constraints: Must be before EndTime.

  • EndTime The timestamp to use for determining the last datapoint to return. This is the last datapoint to fetch, exclusive. For example, 2008-02-26T20:00:00+00:00 (in ISO 8601 format).

  1. $ec2_ebs = new Zend_Service_Amazon_Ec2_CloudWatch('aws_key','aws_secret_key');
  2. $return = $ec2_ebs->getMetricStatistics(
  3.                                      array('MeasureName' => 'NetworkIn',
  4.                                            'Statistics' => array('Average')));
Zend_Service_Amazon_Ec2: Reserved Instances
Zend_Service
Zend Framework手册 中文版
Zend_Service_Amazon_Ec2: Amazon Machine Images (AMI)
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Service
  • 简介
  • Zend_Service_Akismet
  • Zend_Service_Amazon
  • Zend_Service_Amazon_Ec2
  • Zend_Service_Amazon_Ec2: Instances
  • Zend_Service_Amazon_Ec2: Windows Instances
  • Zend_Service_Amazon_Ec2: Reserved Instances
  • Zend_Service_Amazon_Ec2: CloudWatch Monitoring
  • Zend_Service_Amazon_Ec2: Amazon Machine Images (AMI)
  • Zend_Service_Amazon_Ec2: Elastic Block Stroage (EBS)
  • Zend_Service_Amazon_Ec2: Elastic IP Addresses
  • Zend_Service_Amazon_Ec2: Keypairs
  • Zend_Service_Amazon_Ec2: Regions and Availability Zones
  • Zend_Service_Amazon_Ec2: Security Groups
  • Zend_Service_Amazon_S3
  • Zend_Service_Amazon_Sqs
  • Zend_Service_Audioscrobbler
  • Zend_Service_Delicious
  • Zend_Service_DeveloperGarden
  • Zend_Service_Flickr
  • Zend_Service_LiveDocx
  • Zend_Service_Nirvanix
  • Zend_Service_ReCaptcha
  • Zend_Service_Simpy
  • Introduction
  • Zend_Service_StrikeIron
  • Zend_Service_StrikeIron: Bundled Services
  • Zend_Service_StrikeIron: Advanced Uses
  • Zend_Service_Technorati
  • Zend_Service_Twitter
  • Zend_Service_WindowsAzure
  • Zend_Service_Yahoo


Zend_Service_Amazon_Ec2: Elastic Block Stroage (EBS) - Zend Framework Manual

Zend_Service_Amazon_Ec2: Amazon Machine Images (AMI)
Zend_Service
Zend Framework手册 中文版
Zend_Service_Amazon_Ec2: Elastic IP Addresses

Zend_Service_Amazon_Ec2: Elastic Block Stroage (EBS)

Amazon Elastic Block Store (Amazon EBS) is a new type of storage designed specifically for Amazon EC2 instances. Amazon EBS allows you to create volumes that can be mounted as devices by Amazon EC2 instances. Amazon EBS volumes behave like raw unformatted external block devices. They have user supplied device names and provide a block device interface. You can load a file system on top of Amazon EBS volumes, or use them just as you would use a block device.

You can create up to twenty Amazon EBS volumes of any size (from one GiB up to one TiB). Each Amazon EBS volume can be attached to any Amazon EC2 instance in the same Availability Zone or can be left unattached.

Amazon EBS provides the ability to create snapshots of your Amazon EBS volumes to Amazon S3. You can use these snapshots as the starting point for new Amazon EBS volumes and can protect your data for long term durability.

Create EBS Volumes and Snapshots

Example #1 Create a new EBS Volume

Creating a brand new EBS Volume requires the size and which zone you want the EBS Volume to be in.

createNewVolume will return an array containing information about the new Volume which includes the volumeId, size, zone, status and createTime.

  1. $ec2_ebs = new Zend_Service_Amazon_Ec2_Ebs('aws_key','aws_secret_key');
  2. $return = $ec2_ebs->createNewVolume(40, 'us-east-1a');

Example #2 Create an EBS Volume from a Snapshot

Creating an EBS Volume from a snapshot requires the snapshot_id and which zone you want the EBS Volume to be in.

createVolumeFromSnapshot will return an array containing information about the new Volume which includes the volumeId, size, zone, status, createTime and snapshotId.

  1. $ec2_ebs = new Zend_Service_Amazon_Ec2_Ebs('aws_key','aws_secret_key');
  2. $return = $ec2_ebs->createVolumeFromSnapshot('snap-78a54011', 'us-east-1a');

Example #3 Create a Snapshot of an EBS Volume

Creating a Snapshot of an EBS Volume requires the volumeId of the EBS Volume.

createSnapshot will return an array containing information about the new Volume Snapshot which includes the snapshotId, volumeId, status, startTime and progress.

  1. $ec2_ebs = new Zend_Service_Amazon_Ec2_Ebs('aws_key','aws_secret_key');
  2. $return = $ec2_ebs->createSnapshot('volumeId');

Describing EBS Volumes and Snapshots

Example #4 Describing an EBS Volume

describeVolume allows you to get information on an EBS Volume or a set of EBS Volumes. If nothing is passed in then it will return all EBS Volumes. If only one EBS Volume needs to be described a string can be passed in while an array of EBS Volume Id's can be passed in to describe them.

describeVolume will return an array with information about each Volume which includes the volumeId, size, status and createTime. If the volume is attached to an instance, an addition value of attachmentSet will be returned. The attachment set contains information about the instance that the EBS Volume is attached to, which includes volumeId, instanceId, device, status and attachTime.

  1. $ec2_ebs = new Zend_Service_Amazon_Ec2_Ebs('aws_key','aws_secret_key');
  2. $return = $ec2_ebs->describeVolume('volumeId');

Example #5 Describe Attached Volumes

To return a list of EBS Volumes currently attached to a running instance you can call this method. It will only return EBS Volumes attached to the instance with the passed in instanceId.

describeAttachedVolumes returns the same information as the describeVolume but only for the EBS Volumes that are currently attached to the specified instanceId.

  1. $ec2_ebs = new Zend_Service_Amazon_Ec2_Ebs('aws_key','aws_secret_key');
  2. $return = $ec2_ebs->describeAttachedVolumes('instanceId');

Example #6 Describe an EBS Volume Snapshot

describeSnapshot allows you to get information on an EBS Volume Snapshot or a set of EBS Volume Snapshots. If nothing is passed in then it will return information about all EBS Volume Snapshots. If only one EBS Volume Snapshot needs to be described its snapshotId can be passed in while an array of EBS Volume Snapshot Id's can be passed in to describe them.

describeSnapshot will return an array containing information about each EBS Volume Snapshot which includes the snapshotId, volumeId, status, startTime and progress.

  1. $ec2_ebs = new Zend_Service_Amazon_Ec2_Ebs('aws_key','aws_secret_key');
  2. $return = $ec2_ebs->describeSnapshot('volumeId');

Attach and Detaching Volumes from Instances

Example #7 Attaching an EBS Volume

attachVolume will attach an EBS Volume to a running Instance. To attach a volume you need to specify the volumeId, the instanceId and the device (ex: /dev/sdh).

attachVolume will return an array with information about the attach status which contains volumeId, instanceId, device, status and attachTime

  1. $ec2_ebs = new Zend_Service_Amazon_Ec2_Ebs('aws_key','aws_secret_key');
  2. $return = $ec2_ebs->attachVolume('volumeId', 'instanceid', '/dev/sdh');

Example #8 Detaching an EBS Volume

detachVolume will detach an EBS Volume from a running Instance. detachVolume requires that you specify the volumeId with the optional instanceId and device name that was passed when attaching the volume. If you need to force the detachment you can set the forth parameter to be TRUE and it will force the volume to detach.

detachVolume returns an array containing status information about the EBS Volume which includes volumeId, instanceId, device, status and attachTime.

  1. $ec2_ebs = new Zend_Service_Amazon_Ec2_Ebs('aws_key','aws_secret_key');
  2. $return = $ec2_ebs->detachVolume('volumeId');

Note: Forced Detach
 You should only force a detach if the previous detachment attempt did not occur cleanly (logging into an instance, unmounting the volume, and detaching normally). This option can lead to data loss or a corrupted file system. Use this option only as a last resort to detach a volume from a failed instance. The instance will not have an opportunity to flush file system caches or file system meta data. If you use this option, you must perform file system check and repair procedures.

Deleting EBS Volumes and Snapshots

Example #9 Deleting an EBS Volume

deleteVolume will delete an unattached EBS Volume.

deleteVolume will return boolean TRUE or FALSE.

  1. $ec2_ebs = new Zend_Service_Amazon_Ec2_Ebs('aws_key','aws_secret_key');
  2. $return = $ec2_ebs->deleteVolume('volumeId');

Example #10 Deleting an EBS Volume Snapshot

deleteSnapshot will delete an EBS Volume Snapshot.

deleteSnapshot returns booleen TRUE or FALSE.

  1. $ec2_ebs = new Zend_Service_Amazon_Ec2_Ebs('aws_key','aws_secret_key');
  2. $return = $ec2_ebs->deleteSnapshot('snapshotId');
Zend_Service_Amazon_Ec2: Amazon Machine Images (AMI)
Zend_Service
Zend Framework手册 中文版
Zend_Service_Amazon_Ec2: Elastic IP Addresses
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Service
  • 简介
  • Zend_Service_Akismet
  • Zend_Service_Amazon
  • Zend_Service_Amazon_Ec2
  • Zend_Service_Amazon_Ec2: Instances
  • Zend_Service_Amazon_Ec2: Windows Instances
  • Zend_Service_Amazon_Ec2: Reserved Instances
  • Zend_Service_Amazon_Ec2: CloudWatch Monitoring
  • Zend_Service_Amazon_Ec2: Amazon Machine Images (AMI)
  • Zend_Service_Amazon_Ec2: Elastic Block Stroage (EBS)
  • Zend_Service_Amazon_Ec2: Elastic IP Addresses
  • Zend_Service_Amazon_Ec2: Keypairs
  • Zend_Service_Amazon_Ec2: Regions and Availability Zones
  • Zend_Service_Amazon_Ec2: Security Groups
  • Zend_Service_Amazon_S3
  • Zend_Service_Amazon_Sqs
  • Zend_Service_Audioscrobbler
  • Zend_Service_Delicious
  • Zend_Service_DeveloperGarden
  • Zend_Service_Flickr
  • Zend_Service_LiveDocx
  • Zend_Service_Nirvanix
  • Zend_Service_ReCaptcha
  • Zend_Service_Simpy
  • Introduction
  • Zend_Service_StrikeIron
  • Zend_Service_StrikeIron: Bundled Services
  • Zend_Service_StrikeIron: Advanced Uses
  • Zend_Service_Technorati
  • Zend_Service_Twitter
  • Zend_Service_WindowsAzure
  • Zend_Service_Yahoo


Zend_Service_Amazon_Ec2: Elastic IP Addresses - Zend Framework Manual

Zend_Service_Amazon_Ec2: Elastic Block Stroage (EBS)
Zend_Service
Zend Framework手册 中文版
Zend_Service_Amazon_Ec2: Keypairs

Zend_Service_Amazon_Ec2: Elastic IP Addresses

By default, all Amazon EC2 instances are assigned two IP addresses at launch: a private (RFC 1918) address and a public address that is mapped to the private IP address through Network Address Translation (NAT).

If you use dynamic DNS to map an existing DNS name to a new instance's public IP address, it might take up to 24 hours for the IP address to propagate through the Internet. As a result, new instances might not receive traffic while terminated instances continue to receive requests.

To solve this problem, Amazon EC2 provides elastic IP addresses. Elastic IP addresses are static IP addresses designed for dynamic cloud computing. Elastic IP addresses are associated with your account, not specific instances. Any elastic IP addresses that you associate with your account remain associated with your account until you explicitly release them. Unlike traditional static IP addresses, however, elastic IP addresses allow you to mask instance or Availability Zone failures by rapidly remapping your public IP addresses to any instance in your account.

Example #1 Allocating a new Elastic IP

allocate will assign your account a new Elastic IP Address.

allocate returns the newly allocated ip.

  1. $ec2_eip = new Zend_Service_Amazon_Ec2_Elasticip('aws_key','aws_secret_key');
  2. $ip = $ec2_eip->allocate();
  3.
  4. // print out your newly allocated elastic ip address;
  5. print $ip;

Example #2 Describing Allocated Elastic IP Addresses

describe has an optional paramater to describe all of your allocated Elastic IP addresses or just some of your allocated addresses.

describe returns an array that contains information on each Elastic IP Address which contains the publicIp and the instanceId if it is assocated.

  1. $ec2_eip = new Zend_Service_Amazon_Ec2_Elasticip('aws_key','aws_secret_key');
  2. // describe all
  3. $ips = $ec2_eip->describe();
  4.
  5. // describe a subset
  6. $ips = $ec2_eip->describe(array('ip1', 'ip2', 'ip3'));
  7.
  8. // describe a single ip address
  9. $ip = $ec2_eip->describe('ip1');

Example #3 Releasing Elastic IP

release will release an Elastic IP to Amazon.

Returns a boolean TRUE or FALSE.

  1. $ec2_eip = new Zend_Service_Amazon_Ec2_Elasticip('aws_key','aws_secret_key');
  2. $ec2_eip->release('ipaddress');

Example #4 Associates an Elastic IP to an Instance

associate will assign an Elastic IP to an already running instance.

Returns a boolean TRUE or FALSE.

  1. $ec2_eip = new Zend_Service_Amazon_Ec2_Elasticip('aws_key','aws_secret_key');
  2. $ec2_eip->associate('instance_id', 'ipaddress');

Example #5 Disassociate an Elastic IP from an instance

disassociate will disassociate an Elastic IP from an instance. If you terminate an Instance it will automaticly disassociate the Elastic IP address for you.

Returns a boolean TRUE or FALSE.

  1. $ec2_eip = new Zend_Service_Amazon_Ec2_Elasticip('aws_key','aws_secret_key');
  2. $ec2_eip->disassociate('ipaddress');
Zend_Service_Amazon_Ec2: Elastic Block Stroage (EBS)
Zend_Service
Zend Framework手册 中文版
Zend_Service_Amazon_Ec2: Keypairs
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Service
  • 简介
  • Zend_Service_Akismet
  • Zend_Service_Amazon
  • Zend_Service_Amazon_Ec2
  • Zend_Service_Amazon_Ec2: Instances
  • Zend_Service_Amazon_Ec2: Windows Instances
  • Zend_Service_Amazon_Ec2: Reserved Instances
  • Zend_Service_Amazon_Ec2: CloudWatch Monitoring
  • Zend_Service_Amazon_Ec2: Amazon Machine Images (AMI)
  • Zend_Service_Amazon_Ec2: Elastic Block Stroage (EBS)
  • Zend_Service_Amazon_Ec2: Elastic IP Addresses
  • Zend_Service_Amazon_Ec2: Keypairs
  • Zend_Service_Amazon_Ec2: Regions and Availability Zones
  • Zend_Service_Amazon_Ec2: Security Groups
  • Zend_Service_Amazon_S3
  • Zend_Service_Amazon_Sqs
  • Zend_Service_Audioscrobbler
  • Zend_Service_Delicious
  • Zend_Service_DeveloperGarden
  • Zend_Service_Flickr
  • Zend_Service_LiveDocx
  • Zend_Service_Nirvanix
  • Zend_Service_ReCaptcha
  • Zend_Service_Simpy
  • Introduction
  • Zend_Service_StrikeIron
  • Zend_Service_StrikeIron: Bundled Services
  • Zend_Service_StrikeIron: Advanced Uses
  • Zend_Service_Technorati
  • Zend_Service_Twitter
  • Zend_Service_WindowsAzure
  • Zend_Service_Yahoo


Zend_Service_Amazon_Ec2: Amazon Machine Images (AMI) - Zend Framework Manual

Zend_Service_Amazon_Ec2: CloudWatch Monitoring
Zend_Service
Zend Framework手册 中文版
Zend_Service_Amazon_Ec2: Elastic Block Stroage (EBS)

Zend_Service_Amazon_Ec2: Amazon Machine Images (AMI)

Amazon Machine Images (AMIs) are preconfigured with an ever-growing list of operating systems.

AMI Information Utilities

Example #1 Register an AMI with EC2

register Each AMI is associated with an unique ID which is provided by the Amazon EC2 service through the RegisterImage operation. During registration, Amazon EC2 retrieves the specified image manifest from Amazon S3 and verifies that the image is owned by the user registering the image.

register returns the imageId for the registered Image.

  1. $ec2_img = new Zend_Service_Amazon_Ec2_Image('aws_key','aws_secret_key');
  2. $ip = $ec2_img->register('imageLocation');

Example #2 Deregister an AMI with EC2

deregister, Deregisters an AMI. Once deregistered, instances of the AMI can no longer be launched.

deregister returns boolean TRUE or FALSE.

  1. $ec2_img = new Zend_Service_Amazon_Ec2_Image('aws_key','aws_secret_key');
  2. $ip = $ec2_img->deregister('imageId');

Example #3 Describe an AMI

describe Returns information about AMIs, AKIs, and ARIs available to the user. Information returned includes image type, product codes, architecture, and kernel and RAM disk IDs. Images available to the user include public images available for any user to launch, private images owned by the user making the request, and private images owned by other users for which the user has explicit launch permissions.

Launch permissions fall into three categories
Name | Description
public | The owner of the AMI granted launch permissions for the AMI to the all group. All users have launch permissions for these AMIs.
explicit | The owner of the AMI granted launch permissions to a specific user.
implicit | A user has implicit launch permissions for all AMIs he or she owns.

The list of AMIs returned can be modified by specifying AMI IDs, AMI owners, or users with launch permissions. If no options are specified, Amazon EC2 returns all AMIs for which the user has launch permissions.

If you specify one or more AMI IDs, only AMIs that have the specified IDs are returned. If you specify an invalid AMI ID, a fault is returned. If you specify an AMI ID for which you do not have access, it will not be included in the returned results.

If you specify one or more AMI owners, only AMIs from the specified owners and for which you have access are returned. The results can include the account IDs of the specified owners, amazon for AMIs owned by Amazon or self for AMIs that you own.

If you specify a list of executable users, only users that have launch permissions for the AMIs are returned. You can specify account IDs (if you own the AMI(s)), self for AMIs for which you own or have explicit permissions, or all for public AMIs.

describe returns an array for all the images that match the critera that was passed in. The array contains the imageId, imageLocation, imageState, imageOwnerId, isPublic, architecture, imageType, kernelId, ramdiskId and platform.

  1. $ec2_img = new Zend_Service_Amazon_Ec2_Image('aws_key','aws_secret_key');
  2. $ip = $ec2_img->describe();

AMI Attribute Utilities

Example #4 Modify Image Attributes

Modifies an attribute of an AMI

Valid Attributes
Name | Description
launchPermission | Controls who has permission to launch the AMI. Launch permissions can be granted to specific users by adding userIds. To make the AMI public, add the all group.
productCodes | Associates a product code with AMIs. This allows developers to charge users for using AMIs. The user must be signed up for the product before they can launch the AMI. This is a write once attribute; after it is set, it cannot be changed or removed.

modifyAttribute returns boolean TRUE or FALSE.

  1. $ec2_img = new Zend_Service_Amazon_Ec2_Image('aws_key','aws_secret_key');
  2. // modify the launchPermission of an AMI
  3. $return = $ec2_img->modifyAttribute('imageId',
  4.                                     'launchPermission',
  5.                                     'add',
  6.                                     'userId',
  7.                                     'userGroup');
  8.
  9. // set the product code of the AMI.
  10. $return = $ec2_img->modifyAttribute('imageId',
  11.                                     'productCodes',
  12.                                     'add',
  13.                                     null,
  14.                                     null,
  15.                                     'productCode');

Example #5 Reset an AMI Attribute

resetAttribute will reset the attribute of an AMI to its default value. The productCodes attribute cannot be reset.

  1. $ec2_img = new Zend_Service_Amazon_Ec2_Image('aws_key','aws_secret_key');
  2. $return = $ec2_img->resetAttribute('imageId', 'launchPermission');

Example #6 Describe AMI Attribute

describeAttribute returns information about an attribute of an AMI. Only one attribute can be specified per call. Currently only launchPermission and productCodes are supported.

describeAttribute returns an array with the value of the attribute that was requested.

  1. $ec2_img = new Zend_Service_Amazon_Ec2_Image('aws_key','aws_secret_key');
  2. $return = $ec2_img->describeAttribute('imageId', 'launchPermission');
Zend_Service_Amazon_Ec2: CloudWatch Monitoring
Zend_Service
Zend Framework手册 中文版
Zend_Service_Amazon_Ec2: Elastic Block Stroage (EBS)
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Service
  • 简介
  • Zend_Service_Akismet
  • Zend_Service_Amazon
  • Zend_Service_Amazon_Ec2
  • Zend_Service_Amazon_Ec2: Instances
  • Zend_Service_Amazon_Ec2: Windows Instances
  • Zend_Service_Amazon_Ec2: Reserved Instances
  • Zend_Service_Amazon_Ec2: CloudWatch Monitoring
  • Zend_Service_Amazon_Ec2: Amazon Machine Images (AMI)
  • Zend_Service_Amazon_Ec2: Elastic Block Stroage (EBS)
  • Zend_Service_Amazon_Ec2: Elastic IP Addresses
  • Zend_Service_Amazon_Ec2: Keypairs
  • Zend_Service_Amazon_Ec2: Regions and Availability Zones
  • Zend_Service_Amazon_Ec2: Security Groups
  • Zend_Service_Amazon_S3
  • Zend_Service_Amazon_Sqs
  • Zend_Service_Audioscrobbler
  • Zend_Service_Delicious
  • Zend_Service_DeveloperGarden
  • Zend_Service_Flickr
  • Zend_Service_LiveDocx
  • Zend_Service_Nirvanix
  • Zend_Service_ReCaptcha
  • Zend_Service_Simpy
  • Introduction
  • Zend_Service_StrikeIron
  • Zend_Service_StrikeIron: Bundled Services
  • Zend_Service_StrikeIron: Advanced Uses
  • Zend_Service_Technorati
  • Zend_Service_Twitter
  • Zend_Service_WindowsAzure
  • Zend_Service_Yahoo


Zend_Service_Amazon_Ec2: Instances - Zend Framework Manual

Zend_Service_Amazon_Ec2
Zend_Service
Zend Framework手册 中文版
Zend_Service_Amazon_Ec2: Windows Instances

Zend_Service_Amazon_Ec2: Instances

Instance Types

Amazon EC2 instances are grouped into two families: standard and High-CPU. Standard instances have memory to CPU ratios suitable for most general purpose applications; High-CPU instances have proportionally more CPU resources than memory (RAM) and are well suited for compute-intensive applications. When selecting instance types, you might want to use less powerful instance types for your web server instances and more powerful instance types for your database instances. Additionally, you might want to run CPU instance types for CPU-intensive data processing tasks.

One of the advantages of EC2 is that you pay by the instance hour, which makes it convenient and inexpensive to test the performance of your application on different instance families and types. One good way to determine the most appropriate instance family and instance type is to launch test instances and benchmark your application.

Note: Instance Types
 The instance types are defined as constants in the code. Column eight in the table is the defined constant name

Available Instance Types
Type | CPU | Memory | Storage | Platform | I/O | Name | Constant Name
Small | 1 EC2 Compute Unit (1 virtual core with 1 EC2 Compute Unit) | 1.7 GB | 160 GB instance storage (150 GB plus 10 GB root partition) | 32-bit | Moderate | m1.small | Zend_Service_Amazon_Ec2_Instance::SMALL
Large | 4 EC2 Compute Units (2 virtual cores with 2 EC2 Compute Units each) | 7.5 GB | 850 GB instance storage (2 x 420 GB plus 10 GB root partition) | 64-bit | High | m1.large | Zend_Service_Amazon_Ec2_Instance::LARGE
Extra Large | 8 EC2 Compute Units (4 virtual cores with 2 EC2 Compute Units each) | 15 GB | 1,690 GB instance storage (4 x 420 GB plus 10 GB root partition) | 64-bit | High | m1.xlarge | Zend_Service_Amazon_Ec2_Instance::XLARGE
High-CPU Medium | 5 EC2 Compute Units (2 virtual cores with 2.5 EC2 Compute Units each) | 1.7 GB | 350 GB instance storage (340 GB plus 10 GB root partition) | 32-bit | Moderate | c1.medium | Zend_Service_Amazon_Ec2_Instance::HCPU_MEDIUM
High-CPU Extra Large | 20 EC2 Compute Units (8 virtual cores with 2.5 EC2 Compute Units each) | 7 GB | 1,690 GB instance storage (4 x 420 GB plus 10 GB root partition) | 64-bit | High | c1.xlarge | Zend_Service_Amazon_Ec2_Instance::HCPU_XLARGE

Running Amazon EC2 Instances

This section describes the operation methods for maintaining Amazon EC2 Instances.

Example #1 Starting New Ec2 Instances

run will launch a specified number of EC2 Instances. run takes an array of parameters to start, below is a table containing the valid values.

Valid Run Options
Name | Description | Required
imageId | ID of the AMI with which to launch instances. | Yes
minCount | Minimum number of instances to launch. Default: 1 | No
maxCount | Maximum number of instances to launch. Default: 1 | No
keyName | Name of the key pair with which to launch instances. If you do not provide a key, all instances will be inaccessible. | No
securityGroup | Names of the security groups with which to associate the instances. | No
userData | The user data available to the launched instances. This should not be Base64 encoded. | No
instanceType | Specifies the instance type. Default: m1.small | No
placement | Specifies the availability zone in which to launch the instance(s). By default, Amazon EC2 selects an availability zone for you. | No
kernelId | The ID of the kernel with which to launch the instance. | No
ramdiskId | The ID of the RAM disk with which to launch the instance. | No
blockDeviceVirtualName | Specifies the virtual name to map to the corresponding device name. For example: instancestore0 | No
blockDeviceName | Specifies the device to which you are mapping a virtual name. For example: sdb | No
monitor | Turn on AWS CloudWatch Instance Monitoring | No

run will return information about each instance that is starting up.

  1. $ec2_instance = new Zend_Service_Amazon_Ec2_Instance('aws_key',
  2.                                                      'aws_secret_key');
  3. $return = $ec2_instance->run(array('imageId' => 'ami-509320',
  4.                                    'keyName' => 'myKey',
  5.                                    'securityGroup' => array('web',
  6.                                                             'default')));

Example #2 Rebooting an Ec2 Instances

reboot will reboot one or more instances.

This operation is asynchronous; it only queues a request to reboot the specified instance(s). The operation will succeed if the instances are valid and belong to the user. Requests to reboot terminated instances are ignored.

reboot returns boolean TRUE or FALSE

  1. $ec2_instance = new Zend_Service_Amazon_Ec2_Instance('aws_key',
  2.                                                      'aws_secret_key');
  3. $return = $ec2_instance->reboot('instanceId');

Example #3 Terminating an Ec2 Instances

terminate shuts down one or more instances. This operation is idempotent; if you terminate an instance more than once, each call will succeed.

terminate returns boolean TRUE or FALSE

  1. $ec2_instance = new Zend_Service_Amazon_Ec2_Instance('aws_key',
  2.                                                      'aws_secret_key');
  3. $return = $ec2_instance->terminate('instanceId');

Note: Terminated Instances
 Terminated instances will remain visible after termination (approximately one hour).

Amazon Instance Utilities

In this section you will find out how to retreive information, the console output and see if an instance contains a product code.

Example #4 Describing Instances

describe returns information about instances that you own.

If you specify one or more instance IDs, Amazon EC2 returns information for those instances. If you do not specify instance IDs, Amazon EC2 returns information for all relevant instances. If you specify an invalid instance ID, a fault is returned. If you specify an instance that you do not own, it will not be included in the returned results.

describe will return an array containing information on the instance.

  1. $ec2_instance = new Zend_Service_Amazon_Ec2_Instance('aws_key',
  2.                                                      'aws_secret_key');
  3. $return = $ec2_instance->describe('instanceId');

Note: Terminated Instances
 Recently terminated instances might appear in the returned results. This interval is usually less than one hour. If you do not want terminated instances to be returned, pass in a second variable of boolean TRUE to describe and the terminated instances will be ignored.

Example #5 Describing Instances By Image Id

describeByImageId is functionally the same as describe but it will only return the instances that are using the provided imageId.

describeByImageId will return an array containing information on the instances thare were started by the passed in imageId

  1. $ec2_instance = new Zend_Service_Amazon_Ec2_Instance('aws_key',
  2.                                                      'aws_secret_key');
  3. $return = $ec2_instance->describeByImageId('imageId');

Note: Terminated Instances
 Recently terminated instances might appear in the returned results. This interval is usually less than one hour. If you do not want terminated instances to be returned, pass in a second variable of boolean TRUE to describe and the terminated instances will be ignored.

Example #6 Retreiving Console Output

consoleOutput retrieves console output for the specified instance.

Instance console output is buffered and posted shortly after instance boot, reboot, and termination. Amazon EC2 preserves the most recent 64 KB output which will be available for at least one hour after the most recent post.

consoleOutput returns an array containing the instanceId, timestamp from the last output and the output from the console.

  1. $ec2_instance = new Zend_Service_Amazon_Ec2_Instance('aws_key',
  2.                                                      'aws_secret_key');
  3. $return = $ec2_instance->consoleOutput('instanceId');

Example #7 Confirm Product Code on an Instance

confirmProduct returns TRUE if the specified product code is attached to the specified instance. The operation returns FALSE if the product code is not attached to the instance.

The confirmProduct operation can only be executed by the owner of the AMI. This feature is useful when an AMI owner is providing support and wants to verify whether a user's instance is eligible.

  1. $ec2_instance = new Zend_Service_Amazon_Ec2_Instance('aws_key',
  2.                                                      'aws_secret_key');
  3. $return = $ec2_instance->confirmProduct('productCode', 'instanceId');

Example #8 Turn on CloudWatch Monitoring on an Instance(s)

monitor returns the list of instances and their current state of the CloudWatch Monitoring. If the instance does not currently have Monitoring enabled it will be turned on.

  1. $ec2_instance = new Zend_Service_Amazon_Ec2_Instance('aws_key',
  2.                                                      'aws_secret_key');
  3. $return = $ec2_instance->monitor('instanceId');

Example #9 Turn off CloudWatch Monitoring on an Instance(s)

monitor returns the list of instances and their current state of the CloudWatch Monitoring. If the instance currently has Monitoring enabled it will be turned off.

  1. $ec2_instance = new Zend_Service_Amazon_Ec2_Instance('aws_key',
  2.                                                      'aws_secret_key');
  3. $return = $ec2_instance->unmonitor('instanceId');
Zend_Service_Amazon_Ec2
Zend_Service
Zend Framework手册 中文版
Zend_Service_Amazon_Ec2: Windows Instances
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Service
  • 简介
  • Zend_Service_Akismet
  • Zend_Service_Amazon
  • Zend_Service_Amazon_Ec2
  • Zend_Service_Amazon_Ec2: Instances
  • Zend_Service_Amazon_Ec2: Windows Instances
  • Zend_Service_Amazon_Ec2: Reserved Instances
  • Zend_Service_Amazon_Ec2: CloudWatch Monitoring
  • Zend_Service_Amazon_Ec2: Amazon Machine Images (AMI)
  • Zend_Service_Amazon_Ec2: Elastic Block Stroage (EBS)
  • Zend_Service_Amazon_Ec2: Elastic IP Addresses
  • Zend_Service_Amazon_Ec2: Keypairs
  • Zend_Service_Amazon_Ec2: Regions and Availability Zones
  • Zend_Service_Amazon_Ec2: Security Groups
  • Zend_Service_Amazon_S3
  • Zend_Service_Amazon_Sqs
  • Zend_Service_Audioscrobbler
  • Zend_Service_Delicious
  • Zend_Service_DeveloperGarden
  • Zend_Service_Flickr
  • Zend_Service_LiveDocx
  • Zend_Service_Nirvanix
  • Zend_Service_ReCaptcha
  • Zend_Service_Simpy
  • Introduction
  • Zend_Service_StrikeIron
  • Zend_Service_StrikeIron: Bundled Services
  • Zend_Service_StrikeIron: Advanced Uses
  • Zend_Service_Technorati
  • Zend_Service_Twitter
  • Zend_Service_WindowsAzure
  • Zend_Service_Yahoo


Zend_Service_Amazon_Ec2: Keypairs - Zend Framework Manual

Zend_Service_Amazon_Ec2: Elastic IP Addresses
Zend_Service
Zend Framework手册 中文版
Zend_Service_Amazon_Ec2: Regions and Availability Zones

Zend_Service_Amazon_Ec2: Keypairs

Keypairs are used to access instances.

Example #1 Creating a new Amazon Keypair

create, creates a new 2048 bit RSA key pair and returns a unique ID that can be used to reference this key pair when launching new instances.

create returns an array which contains the keyName, keyFingerprint and keyMaterial.

  1. $ec2_kp = new Zend_Service_Amazon_Ec2_Keypair('aws_key','aws_secret_key');
  2. $return = $ec2_kp->create('my-new-key');

Example #2 Deleting an Amazon Keypair

delete, will delete the key pair. This will only prevent it from being used with new instances. Instances currently running with the keypair will still allow you to access them.

delete returns boolean TRUE or FALSE

  1. $ec2_kp = new Zend_Service_Amazon_Ec2_Keypair('aws_key','aws_secret_key');
  2. $return = $ec2_kp->delete('my-new-key');

Example #3 Describe an Amazon Keypair

describe returns information about key pairs available to you. If you specify key pairs, information about those key pairs is returned. Otherwise, information for all registered key pairs is returned.

describe returns an array which contains keyName and keyFingerprint

  1. $ec2_kp = new Zend_Service_Amazon_Ec2_Keypair('aws_key','aws_secret_key');
  2. $return = $ec2_kp->describe('my-new-key');
Zend_Service_Amazon_Ec2: Elastic IP Addresses
Zend_Service
Zend Framework手册 中文版
Zend_Service_Amazon_Ec2: Regions and Availability Zones
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Service
  • 简介
  • Zend_Service_Akismet
  • Zend_Service_Amazon
  • Zend_Service_Amazon_Ec2
  • Zend_Service_Amazon_Ec2: Instances
  • Zend_Service_Amazon_Ec2: Windows Instances
  • Zend_Service_Amazon_Ec2: Reserved Instances
  • Zend_Service_Amazon_Ec2: CloudWatch Monitoring
  • Zend_Service_Amazon_Ec2: Amazon Machine Images (AMI)
  • Zend_Service_Amazon_Ec2: Elastic Block Stroage (EBS)
  • Zend_Service_Amazon_Ec2: Elastic IP Addresses
  • Zend_Service_Amazon_Ec2: Keypairs
  • Zend_Service_Amazon_Ec2: Regions and Availability Zones
  • Zend_Service_Amazon_Ec2: Security Groups
  • Zend_Service_Amazon_S3
  • Zend_Service_Amazon_Sqs
  • Zend_Service_Audioscrobbler
  • Zend_Service_Delicious
  • Zend_Service_DeveloperGarden
  • Zend_Service_Flickr
  • Zend_Service_LiveDocx
  • Zend_Service_Nirvanix
  • Zend_Service_ReCaptcha
  • Zend_Service_Simpy
  • Introduction
  • Zend_Service_StrikeIron
  • Zend_Service_StrikeIron: Bundled Services
  • Zend_Service_StrikeIron: Advanced Uses
  • Zend_Service_Technorati
  • Zend_Service_Twitter
  • Zend_Service_WindowsAzure
  • Zend_Service_Yahoo


Zend_Service_Amazon_Ec2: Reserved Instances - Zend Framework Manual

Zend_Service_Amazon_Ec2: Windows Instances
Zend_Service
Zend Framework手册 中文版
Zend_Service_Amazon_Ec2: CloudWatch Monitoring

Zend_Service_Amazon_Ec2: Reserved Instances

With Amazon EC2 Reserved Instances, you can make a low one-time payment for each instance to reserve and receive a significant discount on the hourly usage charge for that instance.

Amazon EC2 Reserved Instances are based on instance type and location (region and Availability Zone) for a specified period of time (e.g., 1 year or 3 years) and are only available for Linux or UNIX instances.

How Reserved Instances are Applied

Reserved Instances are applied to instances that meet the type/location criteria during the specified period. In this example, a user is running the following instances:

  • (4) m1.small instances in Availability Zone us-east-1a

  • (4) c1.medium instances in Availability Zone us-east-1b

  • (2) c1.xlarge instances in Availability Zone us-east-1b

The user then purchases the following Reserved Instances.

  • (2) m1.small instances in Availability Zone us-east-1a

  • (2) c1.medium instances in Availability Zone us-east-1a

  • (2) m1.xlarge instances in Availability Zone us-east-1a

Amazon EC2 applies the two m1.small Reserved Instances to two of the instances in Availability Zone us-east-1a. Amazon EC2 doesn't apply the two c1.medium Reserved Instances because the c1.medium instances are in a different Availability Zone and does not apply the m1.xlarge Reserved Instances because there are no running m1.xlarge instances.

Reserved Instances Usage

Example #1 Describes Reserved Instances that you purchased

describeInstances() will return information about a reserved instance or instances that you purchased.

describeInstances() returns a multi-demential array that contains reservedInstancesId, instanceType, availabilityZone, duration, fixedPrice, usagePrice, productDescription, instanceCount and state.

  1. $ec2_instance = new Zend_Service_Amazon_Ec2_Instance_Reserved('aws_key',
  2.                                                      'aws_secret_key');
  3. $return = $ec2_instance->describeInstances('instanceId');

Example #2 Describe current Reserved Instance Offerings available

describeOfferings() Describes Reserved Instance offerings that are available for purchase. With Amazon EC2 Reserved Instances, you purchase the right to launch Amazon EC2 instances for a period of time (without getting insufficient capacity errors) and pay a lower usage rate for the actual time used.

describeOfferings() returns a multi-demential array that contains reservedInstancesId, instanceType, availabilityZone, duration, fixedPrice, usagePrice and productDescription.

  1. $ec2_instance = new Zend_Service_Amazon_Ec2_Instance_Reserved('aws_key',
  2.                                                      'aws_secret_key');
  3. $return = $ec2_instance->describeOfferings();

Example #3 Turn off CloudWatch Monitoring on an Instance(s)

purchaseOffering() Purchases a Reserved Instance for use with your account. With Amazon EC2 Reserved Instances, you purchase the right to launch Amazon EC2 instances for a period of time (without getting insufficient capacity errors) and pay a lower usage rate for the actual time used.

purchaseOffering() returns the reservedInstanceId.

  1. $ec2_instance = new Zend_Service_Amazon_Ec2_Instance_Reserved('aws_key',
  2.                                                      'aws_secret_key');
  3. $return = $ec2_instance->purchaseOffering('offeringId', 'instanceCount');
Zend_Service_Amazon_Ec2: Windows Instances
Zend_Service
Zend Framework手册 中文版
Zend_Service_Amazon_Ec2: CloudWatch Monitoring
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Service
  • 简介
  • Zend_Service_Akismet
  • Zend_Service_Amazon
  • Zend_Service_Amazon_Ec2
  • Zend_Service_Amazon_Ec2: Instances
  • Zend_Service_Amazon_Ec2: Windows Instances
  • Zend_Service_Amazon_Ec2: Reserved Instances
  • Zend_Service_Amazon_Ec2: CloudWatch Monitoring
  • Zend_Service_Amazon_Ec2: Amazon Machine Images (AMI)
  • Zend_Service_Amazon_Ec2: Elastic Block Stroage (EBS)
  • Zend_Service_Amazon_Ec2: Elastic IP Addresses
  • Zend_Service_Amazon_Ec2: Keypairs
  • Zend_Service_Amazon_Ec2: Regions and Availability Zones
  • Zend_Service_Amazon_Ec2: Security Groups
  • Zend_Service_Amazon_S3
  • Zend_Service_Amazon_Sqs
  • Zend_Service_Audioscrobbler
  • Zend_Service_Delicious
  • Zend_Service_DeveloperGarden
  • Zend_Service_Flickr
  • Zend_Service_LiveDocx
  • Zend_Service_Nirvanix
  • Zend_Service_ReCaptcha
  • Zend_Service_Simpy
  • Introduction
  • Zend_Service_StrikeIron
  • Zend_Service_StrikeIron: Bundled Services
  • Zend_Service_StrikeIron: Advanced Uses
  • Zend_Service_Technorati
  • Zend_Service_Twitter
  • Zend_Service_WindowsAzure
  • Zend_Service_Yahoo


Zend_Service_Amazon_Ec2: Security Groups - Zend Framework Manual

Zend_Service_Amazon_Ec2: Regions and Availability Zones
Zend_Service
Zend Framework手册 中文版
Zend_Service_Amazon_S3

Zend_Service_Amazon_Ec2: Security Groups

A security group is a named collection of access rules. These access rules specify which ingress (i.e., incoming) network traffic should be delivered to your instance. All other ingress traffic will be discarded.

You can modify rules for a group at any time. The new rules are automatically enforced for all running instances and instances launched in the future.

Note: Maximum Security Groups
 You can create up to 100 security groups.

Security Group Maintenance

Example #1 Create a new Security Group

create a new security group. Every instance is launched in a security group. If no security group is specified during launch, the instances are launched in the default security group. Instances within the same security group have unrestricted network access to each other. Instances will reject network access attempts from other instances in a different security group.

create returns boolean TRUE or FALSE

  1. $ec2_sg = new Zend_Service_Amazon_Ec2_Securitygroups('aws_key',
  2.                                                      'aws_secret_key');
  3. $return = $ec2_sg->create('mygroup', 'my group description');

Example #2 Describe a Security Group

describe returns information about security groups that you own.

If you specify security group names, information about those security groups is returned. Otherwise, information for all security groups is returned. If you specify a group that does not exist, a fault is returned.

describe will return an array containing information about security groups which includes the ownerId, groupName, groupDescription and an array containing all the rules for that security group.

  1. $ec2_sg = new Zend_Service_Amazon_Ec2_Securitygroups('aws_key',
  2.                                                      'aws_secret_key');
  3. $return = $ec2_sg->describe('mygroup');

Example #3 Delete a Security Group

delete will remove the security group. If you attempt to delete a security group that contains instances, a fault is returned. If you attempt to delete a security group that is referenced by another security group, a fault is returned. For example, if security group B has a rule that allows access from security group A, security group A cannot be deleted until the allow rule is removed.

delete returns boolean TRUE or FALSE.

  1. $ec2_sg = new Zend_Service_Amazon_Ec2_Securitygroups('aws_key',
  2.                                                      'aws_secret_key');
  3. $return = $ec2_sg->delete('mygroup');

Authorizing Access

Example #4 Authorizing by IP

authorizeIp Adds permissions to a security group based on an IP address, protocol type and port range.

Permissions are specified by the IP protocol (TCP, UDP or ICMP), the source of the request (by IP range or an Amazon EC2 user-group pair), the source and destination port ranges (for TCP and UDP), and the ICMP codes and types (for ICMP). When authorizing ICMP, -1 can be used as a wildcard in the type and code fields.

Permission changes are propagated to instances within the security group as quickly as possible. However, depending on the number of instances, a small delay might occur.

authorizeIp returns boolean TRUE or FALSE

  1. $ec2_sg = new Zend_Service_Amazon_Ec2_Securitygroups('aws_key',
  2.                                                      'aws_secret_key');
  3. $return = $ec2_sg->authorizeIp('mygroup',
  4.                                 'protocol',
  5.                                 'fromPort',
  6.                                 'toPort',
  7.                                 'ipRange');

Example #5 Authorize By Group

authorizeGroup Adds permissions to a security group.

Permission changes are propagated to instances within the security group as quickly as possible. However, depending on the number of instances, a small delay might occur.

authorizeGroup returns boolean TRUE or FALSE.

  1. $ec2_sg = new Zend_Service_Amazon_Ec2_Securitygroups('aws_key',
  2.                                                      'aws_secret_key');
  3. $return = $ec2_sg->authorizeGroup('mygroup', 'securityGroupName', 'ownerId');

Revoking Access

Example #6 Revoke by IP

revokeIp Revokes permissions to a security group based on an IP address, protocol type and port range. The permissions used to revoke must be specified using the same values used to grant the permissions.

Permissions are specified by the IP protocol (TCP, UDP or ICMP), the source of the request (by IP range or an Amazon EC2 user-group pair), the source and destination port ranges (for TCP and UDP), and the ICMP codes and types (for ICMP). When authorizing ICMP, -1 can be used as a wildcard in the type and code fields.

Permission changes are propagated to instances within the security group as quickly as possible. However, depending on the number of instances, a small delay might occur.

revokeIp returns boolean TRUE or FALSE

  1. $ec2_sg = new Zend_Service_Amazon_Ec2_Securitygroups('aws_key',
  2.                                                      'aws_secret_key');
  3. $return = $ec2_sg->revokeIp('mygroup',
  4.                              'protocol',
  5.                              'fromPort',
  6.                              'toPort',
  7.                              'ipRange');

Example #7 Revoke By Group

revokeGroup Adds permissions to a security group. The permissions to revoke must be specified using the same values used to grant the permissions.

Permission changes are propagated to instances within the security group as quickly as possible. However, depending on the number of instances, a small delay might occur.

revokeGroup returns boolean TRUE or FALSE.

  1. $ec2_sg = new Zend_Service_Amazon_Ec2_Securitygroups('aws_key',
  2.                                                      'aws_secret_key');
  3. $return = $ec2_sg->revokeGroup('mygroup', 'securityGroupName', 'ownerId');
Zend_Service_Amazon_Ec2: Regions and Availability Zones
Zend_Service
Zend Framework手册 中文版
Zend_Service_Amazon_S3
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Service
  • 简介
  • Zend_Service_Akismet
  • Zend_Service_Amazon
  • Zend_Service_Amazon_Ec2
  • Zend_Service_Amazon_Ec2: Instances
  • Zend_Service_Amazon_Ec2: Windows Instances
  • Zend_Service_Amazon_Ec2: Reserved Instances
  • Zend_Service_Amazon_Ec2: CloudWatch Monitoring
  • Zend_Service_Amazon_Ec2: Amazon Machine Images (AMI)
  • Zend_Service_Amazon_Ec2: Elastic Block Stroage (EBS)
  • Zend_Service_Amazon_Ec2: Elastic IP Addresses
  • Zend_Service_Amazon_Ec2: Keypairs
  • Zend_Service_Amazon_Ec2: Regions and Availability Zones
  • Zend_Service_Amazon_Ec2: Security Groups
  • Zend_Service_Amazon_S3
  • Zend_Service_Amazon_Sqs
  • Zend_Service_Audioscrobbler
  • Zend_Service_Delicious
  • Zend_Service_DeveloperGarden
  • Zend_Service_Flickr
  • Zend_Service_LiveDocx
  • Zend_Service_Nirvanix
  • Zend_Service_ReCaptcha
  • Zend_Service_Simpy
  • Introduction
  • Zend_Service_StrikeIron
  • Zend_Service_StrikeIron: Bundled Services
  • Zend_Service_StrikeIron: Advanced Uses
  • Zend_Service_Technorati
  • Zend_Service_Twitter
  • Zend_Service_WindowsAzure
  • Zend_Service_Yahoo


Zend_Service_Amazon_Ec2: Windows Instances - Zend Framework Manual

Zend_Service_Amazon_Ec2: Instances
Zend_Service
Zend Framework手册 中文版
Zend_Service_Amazon_Ec2: Reserved Instances

Zend_Service_Amazon_Ec2: Windows Instances

Using Amazon EC2 instances running Windows is similar to using instances running Linux and UNIX. The following are the major differences between instances that use Linux or UNIX and Windows:

  • Remote Desktop—To access Windows instances, you use Remote Desktop instead of SSH.

  • Administrative Password—To access Windows instances the first time, you must obtain the administrative password using the ec2-get-password command.

  • Simplified Bundling—To bundle a Windows instance, you use a single command that shuts down the instance, saves it as an AMI, and restarts it.

As part of this service, Amazon EC2 instances can now run Microsoft Windows Server 2003. Our base Windows image provides you with most of the common functionality associated with Windows. However, if you require more than two concurrent Windows users or need to leverage applications that require LDAP, Kerberos, RADIUS, or other credential services, you must use Windows with Authentication Services. For example, Microsoft Exchange Server and Microsoft SharePoint Server require Windows with Authentication Services.

Note: To get started using Windows instances, we recommend using the AWS Management Console. There are differences in pricing between Windows and Windows with Authentication Services instances. For information on pricing, go to the Amazon EC2 Product Page.

Amazon EC2 currently provides the following Windows AMIs:

  • Windows Authenticated (32-bit)

  • Windows Authenticated (64-bit)

  • Windows Anonymous (32-bit)

  • Windows Anonymous (64-bit)

The Windows public AMIs that Amazon provides are unmodified versions of Windows with the following two exceptions: we added drivers to improve the networking and disk I/O performance and we created the Amazon EC2 configuration service. The Amazon EC2 configuration service performs the following functions:

  • Randomly sets the Administrator password on initial launch, encrypts the password with the user's SSH key, and reports it to the console. This operation happens upon initial AMI launch. If you change the password, AMIs that are created from this instance use the new password.

  • Configures the computer name to the internal DNS name. To determine the internal DNS name, see Using Instance Addressing.

  • Sends the last three system and application errors from the event log to the console. This helps developers to identify problems that caused an instance to crash or network connectivity to be lost.

Windows Instances Usage

Example #1 Bundles an Amazon EC2 instance running Windows

bundle() has three require paramters and one optional

  • instanceId The instance you want to bundle

  • s3Bucket Where you want the ami to live on S3

  • s3Prefix The prefix you want to assign to the AMI on S3

  • uploadExpiration The expiration of the upload policy. Amazon recommends 12 hours or longer. This is based in nubmer of minutes. Default is 1440 minutes (24 hours)

bundle() returns a multi-demential array that contains instanceId, bundleId, state, startTime, updateTime, progress s3Bucket and s3Prefix.

  1. $ec2_instance = new Zend_Service_Amazon_Ec2_Instance_Windows('aws_key',
  2.                                                      'aws_secret_key');
  3. $return = $ec2_instance->bundle('instanceId', 's3Bucket', 's3Prefix');

Example #2 Describes current bundling tasks

describeBundle() Describes current bundling tasks

describeBundle() returns a multi-demential array that contains instanceId, bundleId, state, startTime, updateTime, progress s3Bucket and s3Prefix.

  1. $ec2_instance = new Zend_Service_Amazon_Ec2_Instance_Windows('aws_key',
  2.                                                      'aws_secret_key');
  3. $return = $ec2_instance->describeBundle('bundleId');

Example #3 Cancels an Amazon EC2 bundling operation

cancelBundle() Cancels an Amazon EC2 bundling operation

cancelBundle() returns a multi-demential array that contains instanceId, bundleId, state, startTime, updateTime, progress s3Bucket and s3Prefix.

  1. $ec2_instance = new Zend_Service_Amazon_Ec2_Instance_Windows('aws_key',
  2.                                                      'aws_secret_key');
  3. $return = $ec2_instance->cancelBundle('bundleId');
Zend_Service_Amazon_Ec2: Instances
Zend_Service
Zend Framework手册 中文版
Zend_Service_Amazon_Ec2: Reserved Instances
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Service
  • 简介
  • Zend_Service_Akismet
  • Zend_Service_Amazon
  • Zend_Service_Amazon_Ec2
  • Zend_Service_Amazon_Ec2: Instances
  • Zend_Service_Amazon_Ec2: Windows Instances
  • Zend_Service_Amazon_Ec2: Reserved Instances
  • Zend_Service_Amazon_Ec2: CloudWatch Monitoring
  • Zend_Service_Amazon_Ec2: Amazon Machine Images (AMI)
  • Zend_Service_Amazon_Ec2: Elastic Block Stroage (EBS)
  • Zend_Service_Amazon_Ec2: Elastic IP Addresses
  • Zend_Service_Amazon_Ec2: Keypairs
  • Zend_Service_Amazon_Ec2: Regions and Availability Zones
  • Zend_Service_Amazon_Ec2: Security Groups
  • Zend_Service_Amazon_S3
  • Zend_Service_Amazon_Sqs
  • Zend_Service_Audioscrobbler
  • Zend_Service_Delicious
  • Zend_Service_DeveloperGarden
  • Zend_Service_Flickr
  • Zend_Service_LiveDocx
  • Zend_Service_Nirvanix
  • Zend_Service_ReCaptcha
  • Zend_Service_Simpy
  • Introduction
  • Zend_Service_StrikeIron
  • Zend_Service_StrikeIron: Bundled Services
  • Zend_Service_StrikeIron: Advanced Uses
  • Zend_Service_Technorati
  • Zend_Service_Twitter
  • Zend_Service_WindowsAzure
  • Zend_Service_Yahoo


Zend_Service_Amazon_Ec2: Regions and Availability Zones - Zend Framework Manual

Zend_Service_Amazon_Ec2: Keypairs
Zend_Service
Zend Framework手册 中文版
Zend_Service_Amazon_Ec2: Security Groups

Zend_Service_Amazon_Ec2: Regions and Availability Zones

Amazon EC2 provides the ability to place instances in different regions and Availability Zones. Regions are dispersed in separate geographic areas or countries. Availability Zones are located within regions and are engineered to be insulated from failures in other Availability Zones and provide inexpensive low latency network connectivity to other Availability Zones in the same region. By launching instances in separate Availability Zones, you can protect your applications from the failure of a single Availability Zone.

Amazon EC2 Regions

Amazon EC2 provides multiple regions so you can launch Amazon EC2 instances in locations that meet your requirements. For example, you might want to launch instances in Europe to be closer to your European customers or to meet legal requirements.

Each Amazon EC2 region is designed to be completely isolated from the other Amazon EC2 regions. This achieves the greatest possible failure independence and stability, and it makes the locality of each EC2 resource unambiguous.

Example #1 Viewing the available regions

describe is used to find out which regions your account has access to.

describe will return an array containing information about which regions are available. Each array will contain regionName and regionUrl.

  1. $ec2_region = new Zend_Service_Amazon_Ec2_Region('aws_key','aws_secret_key');
  2. $regions = $ec2_region->describe();
  3.
  4. foreach($regions as $region) {
  5.     print $region['regionName'] . ' -- ' . $region['regionUrl'] . '<br />';
  6. }

Amazon EC2 Availability Zones

When you launch an instance, you can optionally specify an Availability Zone. If you do not specify an Availability Zone, Amazon EC2 selects one for you in the region that you are using. When launching your initial instances, we recommend accepting the default Availability Zone, which allows Amazon EC2 to select the best Availability Zone for you based on system health and available capacity. Even if you have other instances running, you might consider not specifying an Availability Zone if your new instances do not need to be close to, or separated from, your existing instances.

Example #2 Viewing the available zones

describe is used to find out which what the status is of each availability zone.

describe will return an array containing information about which zones are available. Each array will contain zoneName and zoneState.

  1. $ec2_zones = new Zend_Service_Amazon_Ec2_Availabilityzones('aws_key',
  2.                                                            'aws_secret_key');
  3. $zones = $ec2_zones->describe();
  4.
  5. foreach($zones as $zone) {
  6.     print $zone['zoneName'] . ' -- ' . $zone['zoneState'] . '<br />';
  7. }
Zend_Service_Amazon_Ec2: Keypairs
Zend_Service
Zend Framework手册 中文版
Zend_Service_Amazon_Ec2: Security Groups
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Service
  • 简介
  • Zend_Service_Akismet
  • Zend_Service_Amazon
  • Zend_Service_Amazon_Ec2
  • Zend_Service_Amazon_Ec2: Instances
  • Zend_Service_Amazon_Ec2: Windows Instances
  • Zend_Service_Amazon_Ec2: Reserved Instances
  • Zend_Service_Amazon_Ec2: CloudWatch Monitoring
  • Zend_Service_Amazon_Ec2: Amazon Machine Images (AMI)
  • Zend_Service_Amazon_Ec2: Elastic Block Stroage (EBS)
  • Zend_Service_Amazon_Ec2: Elastic IP Addresses
  • Zend_Service_Amazon_Ec2: Keypairs
  • Zend_Service_Amazon_Ec2: Regions and Availability Zones
  • Zend_Service_Amazon_Ec2: Security Groups
  • Zend_Service_Amazon_S3
  • Zend_Service_Amazon_Sqs
  • Zend_Service_Audioscrobbler
  • Zend_Service_Delicious
  • Zend_Service_DeveloperGarden
  • Zend_Service_Flickr
  • Zend_Service_LiveDocx
  • Zend_Service_Nirvanix
  • Zend_Service_ReCaptcha
  • Zend_Service_Simpy
  • Introduction
  • Zend_Service_StrikeIron
  • Zend_Service_StrikeIron: Bundled Services
  • Zend_Service_StrikeIron: Advanced Uses
  • Zend_Service_Technorati
  • Zend_Service_Twitter
  • Zend_Service_WindowsAzure
  • Zend_Service_Yahoo


Zend_Service_Amazon_S3 - Zend Framework Manual

Zend_Service_Amazon_Ec2: Security Groups
Zend_Service
Zend Framework手册 中文版
Zend_Service_Amazon_Sqs

Zend_Service_Amazon_S3

Introduction

Amazon S3 provides a simple web services interface that can be used to store and retrieve any amount of data, at any time, from anywhere on the web. It gives any developer access to the same highly scalable, reliable, fast, inexpensive data storage infrastructure that Amazon uses to run its own global network of web sites. The service aims to maximize benefits of scale and to pass those benefits on to developers.

Registering with Amazon S3

Before you can get started with Zend_Service_Amazon_S3, you must first register for an account. Please see the » S3 FAQ page on the Amazon website for more information.

After registering, you will receive an application key and a secret key. You will need both to access the S3 service.

API Documentation

The Zend_Service_Amazon_S3 class provides the PHP wrapper to the Amazon S3 REST interface. Please consult the » Amazon S3 documentation for detailed description of the service. You will need to be familiar with basic concepts in order to use this service.

Features

Zend_Service_Amazon_S3 provides the following functionality:

  • A single point for configuring your amazon.s3 authentication credentials that can be used across the amazon.s3 namespaces.

  • A proxy object that is more convenient to use than an HTTP client alone, mostly removing the need to manually construct HTTP POST requests to access the REST service.

  • A response wrapper that parses each response body and throws an exception if an error occurred, alleviating the need to repeatedly check the success of many commands.

  • Additional convenience methods for some of the more common operations.

Getting Started

Once you have registered with Amazon S3, you're ready to store your first data object on the S3. The objects on S3 are stored in containers, called "buckets". Bucket names are unique on S3, and each user can have no more than 100 buckets simultaneously. Each bucket can contain unlimited amount of objects, identified by name.

The following example demonstrates creating a bucket, storing and retrieving the data.

Example #1 Zend_Service_Amazon_S3 Usage Example

  1. require_once 'Zend/Service/Amazon/S3.php';
  2.
  3. $s3 = new Zend_Service_Amazon_S3($my_aws_key, $my_aws_secret_key);
  4.
  5. $s3->createBucket("my-own-bucket");
  6.
  7. $s3->putObject("my-own-bucket/myobject", "somedata");
  8.
  9. echo $s3->getObject("my-own-bucket/myobject");

Since Zend_Service_Amazon_S3 service requires authentication, you should pass your credentials (AWS key and secret key) to the constructor. If you only use one account, you can set default credentials for the service:

  1. require_once 'Zend/Service/Amazon/S3.php';
  2.
  3. Zend_Service_Amazon_S3::setKeys($my_aws_key, $my_aws_secret_key);
  4. $s3 = new Zend_Service_Amazon_S3();

Bucket operations

All objects in S3 system are stored in buckets. Bucket has to be created before any storage operation. Bucket name is unique in the system, so you can not have bucket named the same as someone else's bucket.

Bucket name can contain lowercase letters, digits, periods (.), underscores (_), and dashes (-). No other symbols allowed. Bucket name should start with letter or digit, and be 3 to 255 characters long. Names looking like an IP address (e.g. "192.168.16.255") are not allowed.

  • createBucket() creates a new bucket.

  • cleanBucket() removes all objects that are contained in a bucket.

  • removeBucket() removes the bucket from the system. The bucket should be empty to be removed.

    Example #2 Zend_Service_Amazon_S3 Bucket Removal Example

    1. require_once 'Zend/Service/Amazon/S3.php';
    2.
    3. $s3 = new Zend_Service_Amazon_S3($my_aws_key, $my_aws_secret_key);
    4.
    5. $s3->cleanBucket("my-own-bucket");
    6. $s3->removeBucket("my-own-bucket");

  • getBuckets() returns the list of the names of all buckets belonging to the user.

    Example #3 Zend_Service_Amazon_S3 Bucket Listing Example

    1. require_once 'Zend/Service/Amazon/S3.php';
    2.
    3. $s3 = new Zend_Service_Amazon_S3($my_aws_key, $my_aws_secret_key);
    4.
    5. $list = $s3->getBuckets();
    6. foreach($list as $bucket) {
    7.   echo "I have bucket $bucket\n";
    8. }

  • isBucketAvailable() check if the bucket exists and returns TRUE if it does.

Object operations

The object is the basic storage unit in S3. Object stores unstructured data, which can be any size up to 4 gigabytes. There's no limit on how many objects can be stored on the system.

The object are contained in buckets. Object is identified by name, which can be any utf-8 string. It is common to use hierarchical names (such as Pictures/Myself/CodingInPHP.jpg) to organise object names. Object name is prefixed with bucket name when using object functions, so for object "mydata" in bucket "my-own-bucket" the name would be my-own-bucket/mydata.

Objects can be replaced (by rewriting new data with the same key) or deleted, but not modified, appended, etc. Object is always stored whole.

By default, all objects are private and can be accessed only by their owner. However, it is possible to specify object with public access, in which case it will be available through the URL: http://s3.amazonaws.com/[bucket-name]/[object-name].

  • putObject($object, $data, $meta) created an object with name $object (should contain the bucket name as prefix!) having $data as its content.

    Optional $meta parameter is the array of metadata, which currently supports the following parameters as keys:

    S3_CONTENT_TYPE_HEADER

    MIME content type of the data. If not specified, the type will be guessed according to the file extension of the object name.

    S3_ACL_HEADER

    The access to the item. Following access constants can be used:

    S3_ACL_PRIVATE

    Only the owner has access to the item.

    S3_ACL_PUBLIC_READ

    Anybody can read the object, but only owner can write. This is setting may be used to store publicly accessible content.

    S3_ACL_PUBLIC_WRITE

    Anybody can read or write the object. This policy is rarely useful.

    S3_ACL_AUTH_READ

    Only the owner has write access to the item, and other authenticated S3 users have read access. This is useful for sharing data between S3 accounts without exposing them to the public.

    By default, all the items are private.

    Example #4 Zend_Service_Amazon_S3 Public Object Example

    1. require_once 'Zend/Service/Amazon/S3.php';
    2.
    3. $s3 = new Zend_Service_Amazon_S3($my_aws_key, $my_aws_secret_key);
    4.
    5. $s3->putObject("my-own-bucket/Pictures/Me.png", file_get_contents("me.png"),
    6.     array(Zend_Service_Amazon_S3::S3_ACL_HEADER =>
    7.           Zend_Service_Amazon_S3::S3_ACL_PUBLIC_READ));
    8. // or:
    9. $s3->putFile("me.png", "my-own-bucket/Pictures/Me.png",
    10.     array(Zend_Service_Amazon_S3::S3_ACL_HEADER =>
    11.           Zend_Service_Amazon_S3::S3_ACL_PUBLIC_READ));
    12. echo "Go to http://s3.amazonaws.com/my-own-bucket/Pictures/Me.png to see me!\n";

  • getObject($object) retrieves object data from the storage by name.

  • removeObject($object) removes the object from the storage.

  • getInfo($object) retrieves the metadata information about the object. The function will return array with metadata information. Some of the useful keys are:

    type

    The MIME type of the item.

    size

    The size of the object data.

    mtime

    UNIX-type timestamp of the last modification for the object.

    etag

    The ETag of the data, which is the MD5 hash of the data, surrounded by quotes (").

    The function will return FALSE if the key does not correspond to any existing object.

  • getObjectsByBucket($bucket) returns the list of the object keys, contained in the bucket.

    Example #5 Zend_Service_Amazon_S3 Object Listing Example

    1. require_once 'Zend/Service/Amazon/S3.php';
    2.
    3. $s3 = new Zend_Service_Amazon_S3($my_aws_key, $my_aws_secret_key);
    4.
    5. $list = $s3->getObjectsByBucket("my-own-bucket");
    6. foreach($list as $name) {
    7.   echo "I have $name key:\n";
    8.   $data = $s3->getObject("my-own-bucket/$name");
    9.   echo "with data: $data\n";
    10. }

  • isObjectAvailable($object) checks if the object with given name exists.

  • putFile($path, $object, $meta) puts the content of the file in $path into the object named $object.

    The optional $meta argument is the same as for putObject. If the content type is omitted, it will be guessed basing on the source file name.

Data Streaming

It is possible to get and put objects using not stream data held in memory but files or PHP streams. This is especially useful when file sizes are large in order not to overcome memory limits.

To receive object using streaming, use method getObjectStream($object, $filename). This method will return Zend_Http_Response_Stream, which can be used as described in HTTP Client Data Streaming section.

Example #6 Zend_Service_Amazon_S3 Data Streaming Example

  1. $response = $amazon->getObjectStream("mybycket/zftest");
  2. // copy file
  3. copy($response->getStreamName(), "my/downloads/file");
  4. // use stream
  5. $fp = fopen("my/downloads/file2", "w");
  6. stream_copy_to_stream($response->getStream(), $fp);

Second parameter for getObjectStream() is optional and specifies target file to write the data. If not specified, temporary file is used, which will be deleted after the respons eobject is destroyed.

To send object using streaming, use putFileStream() which has the same signature as putFile() but will use streaming and not read the file into memory.

Also, you can pass stream resource to putObject() method data parameter, in which case the data will be read from the stream when sending the request to the server.

Stream wrapper

In addition to the interfaces described above, Zend_Service_Amazon_S3 also supports operating as a stream wrapper. For this, you need to register the client object as the stream wrapper:

Example #7 Zend_Service_Amazon_S3 Streams Example

  1. require_once 'Zend/Service/Amazon/S3.php';
  2.
  3. $s3 = new Zend_Service_Amazon_S3($my_aws_key, $my_aws_secret_key);
  4.
  5. $s3->registerStreamWrapper("s3");
  6.
  7. mkdir("s3://my-own-bucket");
  8. file_put_contents("s3://my-own-bucket/testdata", "mydata");
  9.
  10. echo file_get_contents("s3://my-own-bucket/testdata");

Directory operations (mkdir, rmdir, opendir, etc.) will operate on buckets and thus their arguments should be of the form of s3://bucketname. File operations operate on objects. Object creation, reading, writing, deletion, stat and directory listing is supported.

Zend_Service_Amazon_Ec2: Security Groups
Zend_Service
Zend Framework手册 中文版
Zend_Service_Amazon_Sqs
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Service
  • 简介
  • Zend_Service_Akismet
  • Zend_Service_Amazon
  • Zend_Service_Amazon_Ec2
  • Zend_Service_Amazon_Ec2: Instances
  • Zend_Service_Amazon_Ec2: Windows Instances
  • Zend_Service_Amazon_Ec2: Reserved Instances
  • Zend_Service_Amazon_Ec2: CloudWatch Monitoring
  • Zend_Service_Amazon_Ec2: Amazon Machine Images (AMI)
  • Zend_Service_Amazon_Ec2: Elastic Block Stroage (EBS)
  • Zend_Service_Amazon_Ec2: Elastic IP Addresses
  • Zend_Service_Amazon_Ec2: Keypairs
  • Zend_Service_Amazon_Ec2: Regions and Availability Zones
  • Zend_Service_Amazon_Ec2: Security Groups
  • Zend_Service_Amazon_S3
  • Zend_Service_Amazon_Sqs
  • Zend_Service_Audioscrobbler
  • Zend_Service_Delicious
  • Zend_Service_DeveloperGarden
  • Zend_Service_Flickr
  • Zend_Service_LiveDocx
  • Zend_Service_Nirvanix
  • Zend_Service_ReCaptcha
  • Zend_Service_Simpy
  • Introduction
  • Zend_Service_StrikeIron
  • Zend_Service_StrikeIron: Bundled Services
  • Zend_Service_StrikeIron: Advanced Uses
  • Zend_Service_Technorati
  • Zend_Service_Twitter
  • Zend_Service_WindowsAzure
  • Zend_Service_Yahoo


Zend_Service_Amazon_Sqs - Zend Framework Manual

Zend_Service_Amazon_S3
Zend_Service
Zend Framework手册 中文版
Zend_Service_Audioscrobbler

Zend_Service_Amazon_Sqs

Introduction

» Amazon Simple Queue Service (Amazon SQS) offers a reliable, highly scalable, hosted queue for storing messages as they travel between computers. By using Amazon SQS, developers can simply move data between distributed components of their applications that perform different tasks, without losing messages or requiring each component to be always available. Amazon SQS makes it easy to build an automated workflow, working in close conjunction with the Amazon Elastic Compute Cloud (Amazon EC2) and the other AWS infrastructure web services.

Amazon SQS works by exposing Amazon's web-scale messaging infrastructure as a web service. Any computer on the Internet can add or read messages without any installed software or special firewall configurations. Components of applications using Amazon SQS can run independently, and do not need to be on the same network, developed with the same technologies, or running at the same time.

Registering with Amazon SQS

Before you can get started with Zend_Service_Amazon_Sqs, you must first register for an account. Please see the » SQS FAQ page on the Amazon website for more information.

After registering, you will receive an application key and a secret key. You will need both to access the SQS service.

API Documentation

The Zend_Service_Amazon_Sqs class provides the PHP wrapper to the Amazon SQS REST interface. Please consult the » Amazon SQS documentation for detailed description of the service. You will need to be familiar with basic concepts in order to use this service.

Features

Zend_Service_Amazon_Sqs provides the following functionality:

  • A single point for configuring your amazon.sqs authentication credentials that can be used across the amazon.sqs namespaces.

  • A proxy object that is more convenient to use than an HTTP client alone, mostly removing the need to manually construct HTTP POST requests to access the REST service.

  • A response wrapper that parses each response body and throws an exception if an error occurred, alleviating the need to repeatedly check the success of many commands.

  • Additional convenience methods for some of the more common operations.

Getting Started

Once you have registered with Amazon SQS, you're ready to create your queue and store some messages on SQS. Each queue can contain unlimited amount of messages, identified by name.

The following example demonstrates creating a queue, storing and retrieving messages.

Example #1 Zend_Service_Amazon_Sqs Usage Example

  1. $sqs = new Zend_Service_Amazon_Sqs($my_aws_key, $my_aws_secret_key);
  2.
  3. $queue_url = $sqs->create('test');
  4.
  5. $message = 'this is a test';
  6. $message_id = $sqs->send($queue_url, $message);
  7.
  8. foreach ($sqs->receive($queue_url) as $message) {
  9.     echo $message['body'].'<br/>';
  10. }

Since the Zend_Service_Amazon_Sqs service requires authentication, you should pass your credentials (AWS key and secret key) to the constructor. If you only use one account, you can set default credentials for the service:

  1. Zend_Service_Amazon_Sqs::setKeys($my_aws_key, $my_aws_secret_key);
  2. $sqs = new Zend_Service_Amazon_Sqs();

Queue operations

All messages SQS are stored in queues. A queue has to be created before any message operations. Queue names must be unique under your access key and secret key.

Queue names can contain lowercase letters, digits, periods (.), underscores (_), and dashes (-). No other symbols allowed. Queue names can be a maximum of 80 characters.

  • create() creates a new queue.

  • delete() removes all messages in the queue.

    Example #2 Zend_Service_Amazon_Sqs Queue Removal Example

    1. $sqs = new Zend_Service_Amazon_Sqs($my_aws_key, $my_aws_secret_key);
    2. $queue_url = $sqs->create('test_1');
    3. $sqs->delete($queue_url);

  • count() gets the approximate number of messages in the queue.

    Example #3 Zend_Service_Amazon_Sqs Queue Count Example

    1. $sqs = new Zend_Service_Amazon_Sqs($my_aws_key, $my_aws_secret_key);
    2. $queue_url = $sqs->create('test_1');
    3. $sqs->send($queue_url, 'this is a test');
    4. $count = $sqs->count($queue_url); // Returns '1'

  • getQueues() returns the list of the names of all queues belonging to the user.

    Example #4 Zend_Service_Amazon_Sqs Queue Listing Example

    1. $sqs = new Zend_Service_Amazon_Sqs($my_aws_key, $my_aws_secret_key);
    2. $list = $sqs->getQueues();
    3. foreach($list as $queue) {
    4.    echo "I have queue $queue\n";
    5. }

Message operations

After a queue is created, simple messages can be sent into the queue then received at a later point in time. Messages can be up to 8KB in length. If longer messages are needed please see » S3. There is no limit to the number of messages a queue can contain.

  • sent($queue_url, $message) send the $message to the $queue_url SQS queue URL.

    Example #5 Zend_Service_Amazon_Sqs Message Send Example

    1. $sqs = new Zend_Service_Amazon_Sqs($my_aws_key, $my_aws_secret_key);
    2. $queue_url = $sqs->create('test_queue');
    3. $sqs->send($queue_url, 'this is a test message');

  • receive($queue_url) retrieves messages from the queue.

    Example #6 Zend_Service_Amazon_Sqs Message Receive Example

    1. $sqs = new Zend_Service_Amazon_Sqs($my_aws_key, $my_aws_secret_key);
    2. $queue_url = $sqs->create('test_queue');
    3. $sqs->send($queue_url, 'this is a test message');
    4. foreach ($sqs->receive($queue_url) as $message) {
    5.     echo "got message ".$message['body'].'<br/>';
    6. }

  • deleteMessage($queue_url, $handle) deletes a message from a queue. A message must first be received using the receive() method before it can be deleted.

    Example #7 Zend_Service_Amazon_Sqs Message Delete Example

    1. $sqs = new Zend_Service_Amazon_Sqs($my_aws_key, $my_aws_secret_key);
    2. $queue_url = $sqs->create('test_queue');
    3. $sqs->send($queue_url, 'this is a test message');
    4. foreach ($sqs->receive($queue_url) as $message) {
    5.     echo "got message ".$message['body'].'<br/>';
    6.
    7.     if ($sqs->deleteMessage($queue_url, $message['handle'])) {
    8.         echo "Message deleted";
    9.     }
    10.     else {
    11.         echo "Message not deleted";
    12.     }
    13. }
Zend_Service_Amazon_S3
Zend_Service
Zend Framework手册 中文版
Zend_Service_Audioscrobbler
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Service
  • 简介
  • Zend_Service_Akismet
  • Zend_Service_Amazon
  • Zend_Service_Amazon_Ec2
  • Zend_Service_Amazon_Ec2: Instances
  • Zend_Service_Amazon_Ec2: Windows Instances
  • Zend_Service_Amazon_Ec2: Reserved Instances
  • Zend_Service_Amazon_Ec2: CloudWatch Monitoring
  • Zend_Service_Amazon_Ec2: Amazon Machine Images (AMI)
  • Zend_Service_Amazon_Ec2: Elastic Block Stroage (EBS)
  • Zend_Service_Amazon_Ec2: Elastic IP Addresses
  • Zend_Service_Amazon_Ec2: Keypairs
  • Zend_Service_Amazon_Ec2: Regions and Availability Zones
  • Zend_Service_Amazon_Ec2: Security Groups
  • Zend_Service_Amazon_S3
  • Zend_Service_Amazon_Sqs
  • Zend_Service_Audioscrobbler
  • Zend_Service_Delicious
  • Zend_Service_DeveloperGarden
  • Zend_Service_Flickr
  • Zend_Service_LiveDocx
  • Zend_Service_Nirvanix
  • Zend_Service_ReCaptcha
  • Zend_Service_Simpy
  • Introduction
  • Zend_Service_StrikeIron
  • Zend_Service_StrikeIron: Bundled Services
  • Zend_Service_StrikeIron: Advanced Uses
  • Zend_Service_Technorati
  • Zend_Service_Twitter
  • Zend_Service_WindowsAzure
  • Zend_Service_Yahoo


Zend_Service_Audioscrobbler - Zend Framework Manual

Zend_Service_Amazon_Sqs
Zend_Service
Zend Framework手册 中文版
Zend_Service_Delicious

Zend_Service_Audioscrobbler

Introduction

Zend_Service_Audioscrobbler is a simple API for using the Audioscrobbler REST Web Service. The Audioscrobbler Web Service provides access to its database of Users, Artists, Albums, Tracks, Tags, Groups, and Forums. The methods of the Zend_Service_Audioscrobbler class begin with one of these terms. The syntax and namespaces of the Audioscrobbler Web Service are mirrored in Zend_Service_Audioscrobbler. For more information about the Audioscrobbler REST Web Service, please visit the » Audioscrobbler Web Service site.

Users

In order to retrieve information for a specific user, the setUser() method is first used to select the user for which data are to be retrieved. Zend_Service_Audioscrobbler provides several methods for retrieving data specific to a single user:

  • userGetProfileInformation(): Returns a SimpleXML object containing the current user's profile information.

  • userGetTopArtists(): Returns a SimpleXML object containing a list of the current user's most listened to artists.

  • userGetTopAlbums(): Returns a SimpleXML object containing a list of the current user's most listened to albums.

  • userGetTopTracks(): Returns a SimpleXML object containing a list of the current user's most listened to tracks.

  • userGetTopTags(): Returns a SimpleXML object containing a list of tags most applied by the current user.

  • userGetTopTagsForArtist(): Requires that an artist be set via setArtist(). Returns a SimpleXML object containing the tags most applied to the current artist by the current user.

  • userGetTopTagsForAlbum(): Requires that an album be set via setAlbum(). Returns a SimpleXML object containing the tags most applied to the current album by the current user.

  • userGetTopTagsForTrack(): Requires that a track be set via setTrack(). Returns a SimpleXML object containing the tags most applied to the current track by the current user.

  • userGetFriends(): Returns a SimpleXML object containing the user names of the current user's friends.

  • userGetNeighbours(): Returns a SimpleXML object containing the user names of people with similar listening habits to the current user.

  • userGetRecentTracks(): Returns a SimpleXML object containing the 10 tracks most recently played by the current user.

  • userGetRecentBannedTracks(): Returns a SimpleXML object containing a list of the 10 tracks most recently banned by the current user.

  • userGetRecentLovedTracks(): Returns a SimpleXML object containing a list of the 10 tracks most recently loved by the current user.

  • userGetRecentJournals(): Returns a SimpleXML object containing a list of the current user's most recent journal entries.

  • userGetWeeklyChartList(): Returns a SimpleXML object containing a list of weeks for which there exist Weekly Charts for the current user.

  • userGetRecentWeeklyArtistChart(): Returns a SimpleXML object containing the most recent Weekly Artist Chart for the current user.

  • userGetRecentWeeklyAlbumChart(): Returns a SimpleXML object containing the most recent Weekly Album Chart for the current user.

  • userGetRecentWeeklyTrackChart(): Returns a SimpleXML object containing the most recent Weekly Track Chart for the current user.

  • userGetPreviousWeeklyArtistChart($fromDate, $toDate): Returns a SimpleXML object containing the Weekly Artist Chart from $fromDate to $toDate for the current user.

  • userGetPreviousWeeklyAlbumChart($fromDate, $toDate): Returns a SimpleXML object containing the Weekly Album Chart from $fromDate to $toDate for the current user.

  • userGetPreviousWeeklyTrackChart($fromDate, $toDate): Returns a SimpleXML object containing the Weekly Track Chart from $fromDate to $toDate for the current user.

Example #1 Retrieving User Profile Information

In this example, we use the setUser() and userGetProfileInformation() methods to retrieve a specific user's profile information:

  1. $as = new Zend_Service_Audioscrobbler();
  2. // Set the user whose profile information we want to retrieve
  3. $as->setUser('BigDaddy71');
  4. // Retrieve BigDaddy71's profile information
  5. $profileInfo = $as->userGetProfileInformation();
  6. // Display some of it
  7. print "Information for $profileInfo->realname "
  8.     . "can be found at $profileInfo->url";

Example #2 Retrieving a User's Weekly Artist Chart

  1. $as = new Zend_Service_Audioscrobbler();
  2. // Set the user whose profile weekly artist chart we want to retrieve
  3. $as->setUser('lo_fye');
  4. // Retrieves a list of previous weeks for which there are chart data
  5. $weeks = $as->userGetWeeklyChartList();
  6. if (count($weeks) < 1) {
  7.     echo 'No data available';
  8. }
  9. sort($weeks); // Order the list of weeks
  10.
  11. $as->setFromDate($weeks[0]); // Set the starting date
  12. $as->setToDate($weeks[0]); // Set the ending date
  13.
  14. $previousWeeklyArtists = $as->userGetPreviousWeeklyArtistChart();
  15.
  16. echo 'Artist Chart For Week Of '
  17.    . date('Y-m-d h:i:s', $as->from_date)
  18.    . '<br />';
  19.
  20. foreach ($previousWeeklyArtists as $artist) {
  21.     // Display the artists' names with links to their profiles
  22.     print '<a href="' . $artist->url . '">' . $artist->name . '</a><br />';
  23. }

Artists

Zend_Service_Audioscrobbler provides several methods for retrieving data about a specific artist, specified via the setArtist() method:

  • artistGetRelatedArtists(): Returns a SimpleXML object containing a list of Artists similar to the current Artist.

  • artistGetTopFans(): Returns a SimpleXML object containing a list of Users who listen most to the current Artist.

  • artistGetTopTracks(): Returns a SimpleXML object containing a list of the current Artist's top-rated Tracks.

  • artistGetTopAlbums(): Returns a SimpleXML object containing a list of the current Artist's top-rated Albums.

  • artistGetTopTags(): Returns a SimpleXML object containing a list of the Tags most frequently applied to current Artist.

Example #3 Retrieving Related Artists

  1. $as = new Zend_Service_Audioscrobbler();
  2. // Set the artist for whom you would like to retrieve related artists
  3. $as->setArtist('LCD Soundsystem');
  4. // Retrieve the related artists
  5. $relatedArtists = $as->artistGetRelatedArtists();
  6. foreach ($relatedArtists as $artist) {
  7.     // Display the related artists
  8.     print '<a href="' . $artist->url . '">' . $artist->name . '</a><br />';
  9. }

Tracks

Zend_Service_Audioscrobbler provides two methods for retrieving data specific to a single track, specified via the setTrack() method:

  • trackGetTopFans(): Returns a SimpleXML object containing a list of Users who listen most to the current Track.

  • trackGetTopTags(): Returns a SimpleXML object containing a list of the Tags most frequently applied to the current Track.

Tags

Zend_Service_Audioscrobbler provides several methods for retrieving data specific to a single tag, specified via the setTag() method:

  • tagGetOverallTopTags(): Returns a SimpleXML object containing a list of Tags most frequently used on Audioscrobbler.

  • tagGetTopArtists(): Returns a SimpleXML object containing a list of Artists to whom the current Tag was most frequently applied.

  • tagGetTopAlbums(): Returns a SimpleXML object containing a list of Albums to which the current Tag was most frequently applied.

  • tagGetTopTracks(): Returns a SimpleXML object containing a list of Tracks to which the current Tag was most frequently applied.

Groups

Zend_Service_Audioscrobbler provides several methods for retrieving data specific to a single group, specified via the setGroup() method:

  • groupGetRecentJournals(): Returns a SimpleXML object containing a list of recent journal posts by Users in the current Group.

  • groupGetWeeklyChart(): Returns a SimpleXML object containing a list of weeks for which there exist Weekly Charts for the current Group.

  • groupGetRecentWeeklyArtistChart(): Returns a SimpleXML object containing the most recent Weekly Artist Chart for the current Group.

  • groupGetRecentWeeklyAlbumChart(): Returns a SimpleXML object containing the most recent Weekly Album Chart for the current Group.

  • groupGetRecentWeeklyTrackChart(): Returns a SimpleXML object containing the most recent Weekly Track Chart for the current Group.

  • groupGetPreviousWeeklyArtistChart($fromDate, $toDate): Requires setFromDate() and setToDate(). Returns a SimpleXML object containing the Weekly Artist Chart from the current fromDate to the current toDate for the current Group.

  • groupGetPreviousWeeklyAlbumChart($fromDate, $toDate): Requires setFromDate() and setToDate(). Returns a SimpleXML object containing the Weekly Album Chart from the current fromDate to the current toDate for the current Group.

  • groupGetPreviousWeeklyTrackChart($fromDate, $toDate): Returns a SimpleXML object containing the Weekly Track Chart from the current fromDate to the current toDate for the current Group.

Forums

Zend_Service_Audioscrobbler provides a method for retrieving data specific to a single forum, specified via the setForum() method:

  • forumGetRecentPosts(): Returns a SimpleXML object containing a list of recent posts in the current forum.

Zend_Service_Amazon_Sqs
Zend_Service
Zend Framework手册 中文版
Zend_Service_Delicious
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Service
  • 简介
  • Zend_Service_Akismet
  • Zend_Service_Amazon
  • Zend_Service_Amazon_Ec2
  • Zend_Service_Amazon_Ec2: Instances
  • Zend_Service_Amazon_Ec2: Windows Instances
  • Zend_Service_Amazon_Ec2: Reserved Instances
  • Zend_Service_Amazon_Ec2: CloudWatch Monitoring
  • Zend_Service_Amazon_Ec2: Amazon Machine Images (AMI)
  • Zend_Service_Amazon_Ec2: Elastic Block Stroage (EBS)
  • Zend_Service_Amazon_Ec2: Elastic IP Addresses
  • Zend_Service_Amazon_Ec2: Keypairs
  • Zend_Service_Amazon_Ec2: Regions and Availability Zones
  • Zend_Service_Amazon_Ec2: Security Groups
  • Zend_Service_Amazon_S3
  • Zend_Service_Amazon_Sqs
  • Zend_Service_Audioscrobbler
  • Zend_Service_Delicious
  • Zend_Service_DeveloperGarden
  • Zend_Service_Flickr
  • Zend_Service_LiveDocx
  • Zend_Service_Nirvanix
  • Zend_Service_ReCaptcha
  • Zend_Service_Simpy
  • Introduction
  • Zend_Service_StrikeIron
  • Zend_Service_StrikeIron: Bundled Services
  • Zend_Service_StrikeIron: Advanced Uses
  • Zend_Service_Technorati
  • Zend_Service_Twitter
  • Zend_Service_WindowsAzure
  • Zend_Service_Yahoo


Zend_Service_Delicious - Zend Framework Manual

Zend_Service_Audioscrobbler
Zend_Service
Zend Framework手册 中文版
Zend_Service_DeveloperGarden

Zend_Service_Delicious

Introduction

Zend_Service_Delicious is simple API for using » del.icio.us XML and JSON web services. This component gives you read-write access to posts at del.icio.us if you provide credentials. It also allows read-only access to public data of all users.

Example #1 Get all posts

  1. $delicious = new Zend_Service_Delicious('username', 'password');
  2. $posts = $delicious->getAllPosts();
  3.
  4. foreach ($posts as $post) {
  5.     echo "--\n";
  6.     echo "Title: {$post->getTitle()}\n";
  7.     echo "Url: {$post->getUrl()}\n";
  8. }

Retrieving posts

Zend_Service_Delicious provides three methods for retrieving posts: getPosts(), getRecentPosts() and getAllPosts(). All of these methods return an instance of Zend_Service_Delicious_PostList, which holds all retrieved posts.

  1. /**
  2. * Get posts matching the arguments. If no date or url is given,
  3. * most recent date will be used.
  4. *
  5. * @param string $tag Optional filtering by tag
  6. * @param Zend_Date $dt Optional filtering by date
  7. * @param string $url Optional filtering by url
  8. * @return Zend_Service_Delicious_PostList
  9. */
  10. public function getPosts($tag = null, $dt = null, $url = null);
  11.
  12. /**
  13. * Get recent posts
  14. *
  15. * @param string $tag   Optional filtering by tag
  16. * @param string $count Maximal number of posts to be returned
  17. *                      (default 15)
  18. * @return Zend_Service_Delicious_PostList
  19. */
  20. public function getRecentPosts($tag = null, $count = 15);
  21.
  22. /**
  23. * Get all posts
  24. *
  25. * @param string $tag Optional filtering by tag
  26. * @return Zend_Service_Delicious_PostList
  27. */
  28. public function getAllPosts($tag = null);

Zend_Service_Delicious_PostList

Instances of this class are returned by the getPosts(), getAllPosts(), getRecentPosts(), and getUserPosts() methods of Zend_Service_Delicious.

For easier data access this class implements the Countable, Iterator, and ArrayAccess interfaces.

Example #2 Accessing post lists

  1. $delicious = new Zend_Service_Delicious('username', 'password');
  2. $posts = $delicious->getAllPosts();
  3.
  4. // count posts
  5. echo count($posts);
  6.
  7. // iterate over posts
  8. foreach ($posts as $post) {
  9.     echo "--\n";
  10.     echo "Title: {$post->getTitle()}\n";
  11.     echo "Url: {$post->getUrl()}\n";
  12. }
  13.
  14. // get post using array access
  15. echo $posts[0]->getTitle();

Note: The ArrayAccess::offsetSet() and ArrayAccess::offsetUnset() methods throw exceptions in this implementation. Thus, code like unset($posts[0]); and $posts[0] = 'A'; will throw exceptions because these properties are read-only.

Post list objects have two built-in filtering capabilities. Post lists may be filtered by tags and by URL.

Example #3 Filtering a Post List with Specific Tags

Posts may be filtered by specific tags using withTags(). As a convenience, withTag() is also provided for when only a single tag needs to be specified.

  1. $delicious = new Zend_Service_Delicious('username', 'password');
  2. $posts = $delicious->getAllPosts();
  3.
  4. // Print posts having "php" and "zend" tags
  5. foreach ($posts->withTags(array('php', 'zend')) as $post) {
  6.     echo "Title: {$post->getTitle()}\n";
  7.     echo "Url: {$post->getUrl()}\n";
  8. }

Example #4 Filtering a Post List by URL

Posts may be filtered by URL matching a specified regular expression using the withUrl() method:

  1. $delicious = new Zend_Service_Delicious('username', 'password');
  2. $posts = $delicious->getAllPosts();
  3.
  4. // Print posts having "help" in the URL
  5. foreach ($posts->withUrl('/help/') as $post) {
  6.     echo "Title: {$post->getTitle()}\n";
  7.     echo "Url: {$post->getUrl()}\n";
  8. }

Editing posts

Example #5 Post editing

  1. $delicious = new Zend_Service_Delicious('username', 'password');
  2. $posts = $delicious->getPosts();
  3.
  4. // set title
  5. $posts[0]->setTitle('New title');
  6. // save changes
  7. $posts[0]->save();

Example #6 Method call chaining

Every setter method returns the post object so that you can chain method calls using a fluent interface.

  1. $delicious = new Zend_Service_Delicious('username', 'password');
  2. $posts = $delicious->getPosts();
  3.
  4. $posts[0]->setTitle('New title')
  5.          ->setNotes('New notes')
  6.          ->save();

Deleting posts

There are two ways to delete a post, by specifying the post URL or by calling the delete() method upon a post object.

Example #7 Deleting posts

  1. $delicious = new Zend_Service_Delicious('username', 'password');
  2.
  3. // by specifying URL
  4. $delicious->deletePost('http://framework.zend.com');
  5.
  6. // or by calling the method upon a post object
  7. $posts = $delicious->getPosts();
  8. $posts[0]->delete();
  9.
  10. // another way of using deletePost()
  11. $delicious->deletePost($posts[0]->getUrl());

Adding new posts

To add a post you first need to call the createNewPost() method, which returns a Zend_Service_Delicious_Post object. When you edit the post, you need to save it to the del.icio.us database by calling the save() method.

Example #8 Adding a post

  1. $delicious = new Zend_Service_Delicious('username', 'password');
  2.
  3. // create a new post and save it (with method call chaining)
  4. $delicious->createNewPost('Zend Framework', 'http://framework.zend.com')
  5.           ->setNotes('Zend Framework Homepage')
  6.           ->save();
  7.
  8. // create a new post and save it  (without method call chaining)
  9. $newPost = $delicious->createNewPost('Zend Framework',
  10.                                      'http://framework.zend.com');
  11. $newPost->setNotes('Zend Framework Homepage');
  12. $newPost->save();

Tags

Example #9 Tags

  1. $delicious = new Zend_Service_Delicious('username', 'password');
  2.
  3. // get all tags
  4. print_r($delicious->getTags());
  5.
  6. // rename tag ZF to zendFramework
  7. $delicious->renameTag('ZF', 'zendFramework');

Bundles

Example #10 Bundles

  1. $delicious = new Zend_Service_Delicious('username', 'password');
  2.
  3. // get all bundles
  4. print_r($delicious->getBundles());
  5.
  6. // delete bundle someBundle
  7. $delicious->deleteBundle('someBundle');
  8.
  9. // add bundle
  10. $delicious->addBundle('newBundle', array('tag1', 'tag2'));

Public data

The del.icio.us web API allows access to the public data of all users.

Methods for retrieving public data
Name | Description | Return type
getUserFans() | Retrieves fans of a user | Array
getUserNetwork() | Retrieves network of a user | Array
getUserPosts() | Retrieves posts of a user | Zend_Service_Delicious_PostList
getUserTags() | Retrieves tags of a user | Array

Note: When using only these methods, a username and password combination is not required when constructing a new Zend_Service_Delicious object.

Example #11 Retrieving public data

  1. // username and password are not required
  2. $delicious = new Zend_Service_Delicious();
  3.
  4. // get fans of user someUser
  5. print_r($delicious->getUserFans('someUser'));
  6.
  7. // get network of user someUser
  8. print_r($delicious->getUserNetwork('someUser'));
  9.
  10. // get tags of user someUser
  11. print_r($delicious->getUserTags('someUser'));

Public posts

When retrieving public posts with the getUserPosts() method, a Zend_Service_Delicious_PostList object is returned, and it contains Zend_Service_Delicious_SimplePost objects, which contain basic information about the posts, including URL, title, notes, and tags.

Methods of the Zend_Service_Delicious_SimplePost class
Name | Description | Return type
getNotes() | Returns notes of a post | String
getTags() | Returns tags of a post | Array
getTitle() | Returns title of a post | String
getUrl() | Returns URL of a post | String

HTTP client

Zend_Service_Delicious uses Zend_Rest_Client for making HTTP requests to the del.icio.us web service. To change which HTTP client Zend_Service_Delicious uses, you need to change the HTTP client of Zend_Rest_Client.

Example #12 Changing the HTTP client of Zend_Rest_Client

  1. $myHttpClient = new My_Http_Client();
  2. Zend_Rest_Client::setHttpClient($myHttpClient);

When you are making more than one request with Zend_Service_Delicious to speed your requests, it's better to configure your HTTP client to keep connections alive.

Example #13 Configuring your HTTP client to keep connections alive

  1. Zend_Rest_Client::getHttpClient()->setConfig(array(
  2.         'keepalive' => true
  3. ));

Note: When a Zend_Service_Delicious object is constructed, the SSL transport of Zend_Rest_Client is set to 'ssl' rather than the default of 'ssl2'. This is because del.icio.us has some problems with 'ssl2', such as requests taking a long time to complete (around 2 seconds).

Zend_Service_Audioscrobbler
Zend_Service
Zend Framework手册 中文版
Zend_Service_DeveloperGarden
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Service
  • 简介
  • Zend_Service_Akismet
  • Zend_Service_Amazon
  • Zend_Service_Amazon_Ec2
  • Zend_Service_Amazon_Ec2: Instances
  • Zend_Service_Amazon_Ec2: Windows Instances
  • Zend_Service_Amazon_Ec2: Reserved Instances
  • Zend_Service_Amazon_Ec2: CloudWatch Monitoring
  • Zend_Service_Amazon_Ec2: Amazon Machine Images (AMI)
  • Zend_Service_Amazon_Ec2: Elastic Block Stroage (EBS)
  • Zend_Service_Amazon_Ec2: Elastic IP Addresses
  • Zend_Service_Amazon_Ec2: Keypairs
  • Zend_Service_Amazon_Ec2: Regions and Availability Zones
  • Zend_Service_Amazon_Ec2: Security Groups
  • Zend_Service_Amazon_S3
  • Zend_Service_Amazon_Sqs
  • Zend_Service_Audioscrobbler
  • Zend_Service_Delicious
  • Zend_Service_DeveloperGarden
  • Zend_Service_Flickr
  • Zend_Service_LiveDocx
  • Zend_Service_Nirvanix
  • Zend_Service_ReCaptcha
  • Zend_Service_Simpy
  • Introduction
  • Zend_Service_StrikeIron
  • Zend_Service_StrikeIron: Bundled Services
  • Zend_Service_StrikeIron: Advanced Uses
  • Zend_Service_Technorati
  • Zend_Service_Twitter
  • Zend_Service_WindowsAzure
  • Zend_Service_Yahoo


Zend_Service_DeveloperGarden - Zend Framework Manual

Zend_Service_Delicious
Zend_Service
Zend Framework手册 中文版
Zend_Service_Flickr

Zend_Service_DeveloperGarden

Introduction to DeveloperGarden

DeveloperGarden is the name for the "Open Development services" of the German Telekom. The "Open Development services" are a set of SOAP API Services.

The family of Zend_Service_DeveloperGarden components provides a clean and simple interface to the » DeveloperGarden API and additionally offers functionality to improve handling and performance.

  • BaseUserService: Class to manage API quota and user accounting details.

  • IpLocation: Locale the given IP and returns geo coordinates. Works only with IPs allocated in the network of the german telekom.

  • LocalSearch: Allows you to search with options nearby or around a given geo coordinate or city.

  • SendSms: Send a Sms or Flash Sms to a given number.

  • SmsValidation: You can validate a number to use it with SendSms for also supply a back channel.

  • VoiceCall: Initiates a call between two numbers.

  • ConferenceCall: You can configure a whole conference room with participants for an adhoc conference or you can also schedule your conference.

The backend SOAP API is documented » here.

Sign Up for an Account

Before you can start using the DeveloperGarden API, you must first » sign up for an account.

The Environment

With the DeveloperGarden API you have the possibility to choose 3 different environments to work on.

  • production: In Production environement you have to pay for calls, sms and other payable services.

  • sandbox: In the Sandbox mode you can use the same features with some limitations like in the production just without to pay for them. Normally during development you can test your application.

  • mock: The Mock environment allows you to build your application and have results but you don not initiate any action on the API side.

For every environment and service are some special features (options) available for testing. Please look » here for details.

Your configuration

You can pass to all classes an array of configuration values. Possible values are:

  • username: Your DeveloperGarden API username.

  • password: Your DeveloperGarden API password.

  • environment: The environment that you selected.

Example #1 Configuration Example

  1. require_once 'Zend/Service/DeveloperGarden/SendSms.php';
  2. $config = array(
  3.     'username'    => 'yourUsername',
  4.     'password'    => 'yourPassword',
  5.     'environment' => Zend_Service_DeveloperGarden_SendSms::ENV_PRODUCTION,
  6. );
  7. $service = new Zend_Service_DeveloperGarden_SendSms($config);

BaseUserService

The class can be used to set and get quota values for the services and to fetch account details.

The getAccountBalance() method is there to fetch an array of account id's with the current balance status (credits).

Example #2 Get account balance example

  1. $service = new Zend_Service_DeveloperGarden_BaseUserService($config);
  2. print_r($service->getAccountBalance());

Get quota information

You can fetch quota informations for a specific service module with the provided methods.

Example #3 Get quota information example

  1. $service = new Zend_Service_DeveloperGarden_BaseUserService($config);
  2. $result = $service->getSmsQuotaInformation(
  3.     Zend_Service_DeveloperGarden_BaseUserService::ENV_PRODUCTION
  4. );
  5. echo 'Sms Quota:<br />';
  6. echo 'Max Quota: ', $result->getMaxQuota(), '<br />';
  7. echo 'Max User Quota: ', $result->getMaxUserQuota(), '<br />';
  8. echo 'Quota Level: ', $result->getQuotaLevel(), '<br />';

You get a Result object that contains all information that you need, optional you can pass to the QuotaInformation method the environment constant to fetch the quota for the specific environment.

Here a list of all getQuotaInformation methods:

  • getConfernceCallQuotaInformation()

  • getIPLocationQuotaInformation()

  • getLocalSearchQuotaInformation()

  • getSmsQuotaInformation()

  • getVoiceCallQuotaInformation()

Change quota information

To change the current quota use one of the changeQuotaPool methods. First parameter is the new pool value and the second one is the environment.

Example #4 Change quota information example

  1. $service = new Zend_Service_DeveloperGarden_BaseUserService($config);
  2. $result = $service->changeSmsQuotaPool(
  3.     1000,
  4.     Zend_Service_DeveloperGarden_BaseUserService::ENV_PRODUCTION
  5. );
  6. if (!$result->hasError()) {
  7.     echo 'updated Quota Pool';
  8. }

Here a list of all changeQuotaPool methods:

  • changeConferenceCallQuotaPool()

  • changeIPLocationQuotaPool()

  • changeLocalSearchQuotaPool()

  • changeSmsQuotaPool()

  • changeVoiceCallQuotaPool()

IP Location

This service allows you to retrieve location information for a given IP address.

There are some limitations:

  • The IP address must be in the T-Home network

  • Just the next big city will be resolved

  • IPv6 is not supported yet

Example #5 Locate a given IP

  1. $service = new Zend_Service_DeveloperGarden_IpLocation($config);
  2. $service->setEnvironment(
  3.     Zend_Service_DeveloperGarden_IpLocation::ENV_MOCK
  4. );
  5. $ip = new Zend_Service_DeveloperGarden_IpLocation_IpAddress('127.0.0.1');
  6. print_r($service->locateIp($ip));

Local Search

The Local Search service provides the local search machine » suchen.de via a the web service interface. For more details, refer to » the documentation.

Example #6 Locate a Restaurant

  1. $service = new Zend_Service_DeveloperGarden_LocalSearch($config);
  2. $search  = new Zend_Service_DeveloperGarden_LocalSearch_SearchParameters();
  3. /**
  4. * @see http://www.developergarden.com/static/docu/en/ch04s02s06s04.html
  5. */
  6. $search->setWhat('pizza')
  7.        ->setWhere('jena');
  8. print_r($service->localSearch($search));

Send SMS

The Send SMS service is used to send normal and Flash SMS to any number.

The following restrictions apply to the use of the SMS service:

  • An SMS or Flash SMS in the production environment must not be longer than 765 characters and must not be sent to more than 10 recipients.

  • An SMS or Flash SMS in the sandbox environment is shortened and enhanced by a note in the DeveloperGarden. The maximum length of the message sent is 160 characters.

  • In the sandbox environment, a maximum of 10 SMS can be sent per day.

  • The following characters are counted twice: | ^ € { } [ ] ~ \ LF (line break)

  • If an SMS or Flash SMS is longer than 160 characters, one message is charged for each 153 characters (quota and credit).

  • Delivery cannot be guaranteed for SMS or Flash SMS to landline numbers.

  • The sender can exist of a maximum of 11 characters. Permitted characters are letters and numbers.

  • The specification of a phone number as the sender is only permitted if the phone number has been validated. (See: SMS Validation)

Example #7 Sending an SMS

  1. $service = new Zend_Service_DeveloperGarden_SendSms($config);
  2. $sms = $service->createSms(
  3.     '+49-172-123456; +49-177-789012',
  4.     'your test message',
  5.     'yourname'
  6. );
  7. print_r($service->send($sms));

SMS Validation

The SMS Validation service allows the validation of physical phone number to be used as the sender of an SMS.

First, call setValidationKeyword() to receive an SMS with a keyword.

After you get your keyword, you have to use the validate() to validate your number with the keyword against the service.

With the method getValidatedNumbers(), you will get a list of all already validated numbers and the status of each.

Example #8 Request validation keyword

  1. $service = new Zend_Service_DeveloperGarden_SmsValidation($config);
  2. print_r($service->sendValidationKeyword('+49-172-123456'));

Example #9 Validate a number with a keyword

  1. $service = new Zend_Service_DeveloperGarden_SmsValidation($config);
  2. print_r($service->validate('TheKeyWord', '+49-172-123456'));

To invalidate a validated number, call the method inValidate().

Voice Call

The Voice Call service is used for setting up a voice connection between two telephone connections. For specific details please read the » API Documentation.

Normally the Service works as followed:

  • Call the first participant.

  • If the connection is successful, call the second participant.

  • If second participant connects succesfully, both participants are connected.

  • The call is open until one of the participants hangs up or the expire mechanism intercepts.

Example #10 Call two numbers

  1. $service = new Zend_Service_DeveloperGarden_VoiceCall($config);
  2. $aNumber = '+49-30-000001';
  3. $bNumber = '+49-30-000002';
  4. $expiration  = 30;  // seconds
  5. $maxDuration = 300; // 5 mins
  6. $newCall = $service->newCall($aNumber, $bNumber, $expiration, $maxDuration);
  7. echo $newCall->getSessionId();

If the call is initiated, you can ask the result object for the session ID and use this session ID for an additional call to the callStatus or tearDownCall() methods. The second parameter on the callStatus() method call extends the expiration for this call.

Example #11 Call two numbers, ask for status, and cancel

  1. $service = new Zend_Service_DeveloperGarden_VoiceCall($config);
  2. $aNumber = '+49-30-000001';
  3. $bNumber = '+49-30-000002';
  4. $expiration  = 30; // seconds
  5. $maxDuration = 300; // 5 mins
  6.
  7. $newCall = $service->newCall($aNumber, $bNumber, $expiration, $maxDuration);
  8.
  9. $sessionId = $newCall->getSessionId();
  10.
  11. $service->callStatus($sessionId, true); // extend the call
  12.
  13. sleep(10); // sleep 10s and then tearDown
  14.
  15. $service->tearDownCall($sessionId);

ConferenceCall

Conference Call allows you to setup and start a phone conference.

The following features are available:

  • Conferences with an immediate start

  • Conferences with a defined start date

  • Recurring conference series

  • Adding, removing, and muting of participants from a conference

  • Templates for conferences

Here is a list of currently implemented API methods:

  • createConference() creates a new conference

  • updateConference() updates an existing conference

  • commitConference() saves the conference, and, if no date is configured, immediately starts the conference

  • removeConference() removes a conference

  • getConferenceList() returns a list of all configured conferences

  • getConferenceStatus() displays information for an existing conference

  • getParticipantStatus() displays status information about a conference participant

  • newParticipant() creates a new participant

  • addParticipant() adds a participant to a conference

  • updateParticipant() updates a participant, usually to mute or redial the participant

  • removeParticipant() removes a participant from a conference

  • getRunningConference() requests the running instance of a planned conference

  • createConferenceTemplate() creates a new conference template

  • getConferenceTemplate() requests an existing conference template

  • updateConferenceTemplate() updates existing conference template details

  • removeConferenceTemplate() removes a conference template

  • getConferenceTemplateList() requests all conference templates of an owner

  • addConferenceTemplateParticipant() adds a conference participant to conference template

  • getConferenceTemplateParticipant() displays details of a participant of a conference template

  • updateConferenceTemplateParticipant() updates participant details within a conference template

  • removeConferenceTemplateParticipant() removes a participant from a conference template

Example #12 Ad-Hoc conference

  1. $client = new Zend_Service_DeveloperGarden_ConferenceCall($config);
  2.
  3. $conferenceDetails = new Zend_Service_DeveloperGarden_ConferenceCall_ConferenceDetail(
  4.     'Zend-Conference',                    // name for the conference
  5.     'this is my private zend conference', // description
  6.     60                                    // duration in seconds
  7. );
  8.
  9. $conference = $client->createConference('MyName', $conferenceDetails);
  10.
  11. $part1 = new Zend_Service_DeveloperGarden_ConferenceCall_ParticipantDetail(
  12.     'Jon',
  13.     'Doe',
  14.     '+49-123-4321',
  15.     'your.name@example.com',
  16.     true
  17. );
  18.
  19. $client->newParticipant($conference->getConferenceId(), $part1);
  20. // add a second, third ... participant
  21.
  22. $client->commitConference($conference->getConferenceId());

Performance and Caching

You can setup various caching options to improve the performance for resolving WSDL and authentication tokens.

First of all, you can setup the internal SoapClient (PHP) caching values.

Example #13 WSDL cache options

  1. Zend_Service_DeveloperGarden_SecurityTokenServer_Cache::setWsdlCache([PHP CONSTANT]);

The [PHP CONSTANT] can be one of the following values:

  • WSDL_CACHE_DISC: enabled disc caching

  • WSDL_CACHE_MEMORY: enabled memory caching

  • WSDL_CACHE_BOTH: enabled disc and memory caching

  • WSDL_CACHE_NONE: disabled both caching

If you want also to cache the result for calls to the SecuritTokenServer you can setup a Zend_Cache instance and pass it to the setCache().

Example #14 SecurityTokenServer cache option

  1. $cache = Zend_Cache::factory('Core', ...);
  2. Zend_Service_DeveloperGarden_SecurityTokenServer_Cache::setCache($cache);
Zend_Service_Delicious
Zend_Service
Zend Framework手册 中文版
Zend_Service_Flickr
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Service
  • 简介
  • Zend_Service_Akismet
  • Zend_Service_Amazon
  • Zend_Service_Amazon_Ec2
  • Zend_Service_Amazon_Ec2: Instances
  • Zend_Service_Amazon_Ec2: Windows Instances
  • Zend_Service_Amazon_Ec2: Reserved Instances
  • Zend_Service_Amazon_Ec2: CloudWatch Monitoring
  • Zend_Service_Amazon_Ec2: Amazon Machine Images (AMI)
  • Zend_Service_Amazon_Ec2: Elastic Block Stroage (EBS)
  • Zend_Service_Amazon_Ec2: Elastic IP Addresses
  • Zend_Service_Amazon_Ec2: Keypairs
  • Zend_Service_Amazon_Ec2: Regions and Availability Zones
  • Zend_Service_Amazon_Ec2: Security Groups
  • Zend_Service_Amazon_S3
  • Zend_Service_Amazon_Sqs
  • Zend_Service_Audioscrobbler
  • Zend_Service_Delicious
  • Zend_Service_DeveloperGarden
  • Zend_Service_Flickr
  • Zend_Service_LiveDocx
  • Zend_Service_Nirvanix
  • Zend_Service_ReCaptcha
  • Zend_Service_Simpy
  • Introduction
  • Zend_Service_StrikeIron
  • Zend_Service_StrikeIron: Bundled Services
  • Zend_Service_StrikeIron: Advanced Uses
  • Zend_Service_Technorati
  • Zend_Service_Twitter
  • Zend_Service_WindowsAzure
  • Zend_Service_Yahoo


Zend_Service_Flickr - Zend Framework Manual

Zend_Service_DeveloperGarden
Zend_Service
Zend Framework手册 中文版
Zend_Service_LiveDocx

Zend_Service_Flickr

对Flickr搜索的介绍

Zend_Service_Flickr i是一组用来使用Flickr REST Web Service 的简单API. 为了可以使用Flickr web services, 你必须拥有 API key. 获取key或需要Flickr REST Web Service更多详细信息, 请访问 » Flickr API Documentation.

在下面的例子中, 我们使用 tagSearch() 方法来搜索tag中有 "php"的照片 .

Example #1 简单的 Flickr 照片搜索

<?php
require_once 'Zend/Service/Flickr.php';

$flickr = new Zend_Service_Flickr('MY_API_KEY');

$results = $flickr->tagSearch("php");

foreach ($results as $result) {
    echo $result->title . '<br />';
}
?>

Note: tagSearch() 可以接受第二个(可选的)参数提供更多选项.

查找 Flickr 用户

Zend_Service_Flickr 提供三种不同的方法来得到 Flickr的用户信息:

  • userSearch(): 接受一个以空格来作为分隔符的(由tag构成)查询字符串，用数组的方式(可选)来指定搜索选项, 返回一个 Zend_Service_Flickr_ResultSet 对象.

  • getIdByUsername(): 以字符串的格式返回与给定用户名关联的用户 ID

  • getIdByEmail(): 以字符串的格式返回与给定email地址关联的用户 ID

Example #2 用email地址来查找Flickr用户

在这个例子中, 我们有一个Flickr用户的e-mail 地址, 并用 userSearch() 方法获得用户的信息:

<?php
require_once 'Zend/Service/Flickr.php';

$flickr = new Zend_Service_Flickr('MY_API_KEY');

$results = $flickr->userSearch($userEmail);

foreach ($results as $result) {
    echo $result->title . '<br />';
}
?>

获得 Flickr 图像详细资料

Zend_Service_Flickr使我们可以使用给定的图像id来非常方便快捷的得到图像的详细信息,使用getImageDetails() 方法, 如下面的例子:

Example #3 获得 Flickr 图像详细资料

一旦你有一个Flickr 图像的ID,获得它的详细信息将是小事一桩:

<?php
require_once 'Zend/Service/Flickr.php';

$flickr = new Zend_Service_Flickr('MY_API_KEY');

$image = $flickr->getImageDetails($imageId);

echo "Image ID $imageId is $image->width x $image->height pixels.<br />\n";
echo "<a href=\"$image->clickUri\">Click for Image</a>\n";
?>

Zend_Service_Flickr 类

下面列出的是将由tagSearch() 和 userSearch()返回的一些类:

  • Zend_Service_Flickr_ResultSet

  • Zend_Service_Flickr_Result

  • Zend_Service_Flickr_Image

Zend_Service_Flickr_ResultSet

代表一个Flickr search的结果集.

Note: 该对象实现了 SeekableIterator 接口,我们可以很方便的进行遍历 (如 foreach ), 也可以用 seek()直接访问指定的结果 . .

属性

Zend_Service_Flickr_ResultSet 属性
名称 | 类别 | 描述
totalResultsAvailable | int | 所有有效结果的数量
totalResultsReturned | int | 所有结果的数量
firstResultPosition | int | 当前结果集在所有结果集中的偏移

Zend_Service_Flickr_ResultSet::totalResults()

int totalResults ( void )

返回这个结果集中所有结果的数量

Back to Class List

Zend_Service_Flickr_Result

Flickr query中的一个单一图片结果

属性

Zend_Service_Flickr_Result 属性
名称 | 类别 | 描述
id | int | 图片 ID
owner | int | 相片所有者的 NSID.
secret | string | 一个用于构建url的key
server | string | 用于构建url的服务器名称
title | string | 相片的title
ispublic | boolean | 相片是否是公开的
isfriend | boolean | 因为你是相片所有者的朋友，相片对你可见
isfamily | boolean | 因为你是相片所有者的亲属，相片对你可见
license | string | 相片基于什么license
date_upload | string | 上传相片的时间
date_taken | string | 拍照的时间
owner_name | string | 相片所有者的名字
icon_server | string | 用来装配图标 URLs的服务器
Square | Zend_Service_Flickr_Image | 一个 75x75像素大小的预览图
Thumbnail | Zend_Service_Flickr_Image | 一个100像素大小的预览图
Small | Zend_Service_Flickr_Image | 一个240像素大小的图片
Medium | Zend_Service_Flickr_Image | 一个500像素大小的图片
Large | Zend_Service_Flickr_Image | 一个640像素大小的图片
Original | Zend_Service_Flickr_Image | 原始图片

Back to Class List

Zend_Service_Flickr_Image

代表由Flickr搜索返回的图片

属性

Zend_Service_Flickr_Image 属性
名称 | 类别 | 描述
uri | string | 原始图片的URI
clickUri | string | 图片相关的可点击的URI (如 Flickr 的页面)
width | int | 图片的宽度
height | int | 图片的高度

Back to Class List

Zend_Service_DeveloperGarden
Zend_Service
Zend Framework手册 中文版
Zend_Service_LiveDocx
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Service
  • 简介
  • Zend_Service_Akismet
  • Zend_Service_Amazon
  • Zend_Service_Amazon_Ec2
  • Zend_Service_Amazon_Ec2: Instances
  • Zend_Service_Amazon_Ec2: Windows Instances
  • Zend_Service_Amazon_Ec2: Reserved Instances
  • Zend_Service_Amazon_Ec2: CloudWatch Monitoring
  • Zend_Service_Amazon_Ec2: Amazon Machine Images (AMI)
  • Zend_Service_Amazon_Ec2: Elastic Block Stroage (EBS)
  • Zend_Service_Amazon_Ec2: Elastic IP Addresses
  • Zend_Service_Amazon_Ec2: Keypairs
  • Zend_Service_Amazon_Ec2: Regions and Availability Zones
  • Zend_Service_Amazon_Ec2: Security Groups
  • Zend_Service_Amazon_S3
  • Zend_Service_Amazon_Sqs
  • Zend_Service_Audioscrobbler
  • Zend_Service_Delicious
  • Zend_Service_DeveloperGarden
  • Zend_Service_Flickr
  • Zend_Service_LiveDocx
  • Zend_Service_Nirvanix
  • Zend_Service_ReCaptcha
  • Zend_Service_Simpy
  • Introduction
  • Zend_Service_StrikeIron
  • Zend_Service_StrikeIron: Bundled Services
  • Zend_Service_StrikeIron: Advanced Uses
  • Zend_Service_Technorati
  • Zend_Service_Twitter
  • Zend_Service_WindowsAzure
  • Zend_Service_Yahoo


Zend_Service_LiveDocx - Zend Framework Manual

Zend_Service_Flickr
Zend_Service
Zend Framework手册 中文版
Zend_Service_Nirvanix

Zend_Service_LiveDocx

Introduction to LiveDocx

LiveDocx is a SOAP service that allows developers to generate word processing documents by combining structured data from PHP with a template, created in a word processor. The resulting document can be saved as a PDF, DOCX, DOC, HTML or RTF file. LiveDocx implements » mail-merge in PHP.

The family of Zend_Service_LiveDocx components provides a clean and simple interface to the » LiveDocx API and additionally offers functionality to improve network performance.

In addition to this section of the manual, if you are interested in learning more about Zend_Service_LiveDocx and the backend SOAP service LiveDocx, please take a look at the following resources:

  • Shipped demonstration applications. There are a large number of demonstration applications in the directory /demos/Zend/Service/LiveDocx of the Zend Framework distribution file or trunk version, checked out of the standard SVN repository. These are designed to get you up to speed with Zend_Service_LiveDocx within a matter of minutes.

  • » Zend_Service_LiveDocx blog and web site.

  • » LiveDocx SOAP API documentation.

  • » LiveDocx WSDL.

  • » LiveDocx blog and web site.

Sign Up for an Account

Before you can start using LiveDocx, you must first » sign up for an account. The account is completely free of charge and you only need to specify a username, password and e-mail address. Your login credentials will be dispatched to the e-mail address you supply, so please type carefully.

Templates and Documents

LiveDocx differentiates between the following terms: 1) template and 2) document. In order to fully understand the documentation and indeed the actual API, it is important that any programmer deploying LiveDocx understands the difference.

The term template is used to refer to the input file, created in a word processor, containing formatting and text fields. You can download an » example template, stored as a DOCX file. The term document is used to refer to the output file that contains the template file, populated with data - i.e. the finished document. You can download an » example document, stored as a PDF file.

Supported File Formats

LiveDocx supports the following file formats:

Template File Formats (input)

Templates can be saved in any of the following file formats:

  • » DOCX - Office Open XML format

  • » DOC - Microsoft Word DOC format

  • » RTF - Rich text file format

  • » TXD - TX Text Control format

Document File Formats (output):

The resulting document can be saved in any of the following file formats:

  • » DOCX - Office Open XML format

  • » DOC - Microsoft Word DOC format

  • » HTML - XHTML 1.0 transitional format

  • » RTF - Rich text file format

  • » PDF - Acrobat Portable Document Format

  • » TXD - TX Text Control format

  • » TXT - ANSI plain text

Image File Formats (output):

The resulting document can be saved in any of the following graphical file formats:

  • » BMP - Bitmap image format

  • » GIF - Graphics Interchange Format

  • » JPG - Joint Photographic Experts Group format

  • » PNG - Portable Network Graphics format

  • » TIFF - Tagged Image File Format

  • » WMF - Windows Meta File format

Zend_Service_LiveDocx_MailMerge

Zend_Service_LiveDocx_MailMerge is the mail-merge object in the Zend_Service_LiveDocx family.

Document Generation Process

The document generation process can be simplified with the following equation:

Template + Data = Document

Or expressed by the following diagram:

< class="inlinemediaobject">

Data is inserted into template to create a document (» view larger).

A template, created in a word processing application, such as Microsoft Word, is loaded into LiveDocx. Data is then inserted into the template and the resulting document is saved to any supported format.

Creating Templates in Microsoft Word 2007

Start off by launching Microsoft Word and creating a new document. Next, open up the Field dialog box. This looks as follows:

< class="inlinemediaobject">

Microsoft Word 2007 Field dialog box (» view larger).

Using this dialog, you can insert the required merge fields into your document. Below is a screenshot of a license agreement in Microsoft Word 2007. The merge fields are marked as { MERGEFIELD FieldName }:

< class="inlinemediaobject">

Template in Microsoft Word 2007 (» view larger).

Now, save the template as template.docx.

In the next step, we are going to populate the merge fields with textual data from PHP.

< class="inlinemediaobject">

Cropped template in Microsoft Word 2007 (» view larger).

To populate the merge fields in the above cropped screenshot of the » template in Microsoft Word, all we have to code is as follows:

  1. $phpLiveDocx = new Zend_Service_LiveDocx_MailMerge();
  2.
  3. $phpLiveDocx->setUsername('myUsername')
  4.             ->setPassword('myPassword');
  5.
  6. $phpLiveDocx->setLocalTemplate('template.docx');
  7.
  8. $phpLiveDocx->assign('software', 'Magic Graphical Compression Suite v1.9')
  9.             ->assign('licensee', 'Henry Döner-Meyer')
  10.             ->assign('company',  'Co-Operation');
  11.
  12. $phpLiveDocx->createDocument();
  13.
  14. $document = $phpLiveDocx->retrieveDocument('pdf');
  15.
  16. file_put_contents('document.pdf', $document);

The resulting document is written to disk in the file document.pdf. This file can now be post-processed, sent via e-mail or simply displayed, as is illustrated below in Document Viewer 2.26.1 on Ubuntu 9.04:

< class="inlinemediaobject">

Resulting document as PDF in Document Viewer 2.26.1 (» view larger).

Advanced Mail-Merge

Zend_Service_LiveDocx_MailMerge allows designers to insert any number of text fields into a template. These text fields are populated with data when createDocument() is called.

In addition to text fields, it is also possible specify regions of a document, which should be repeated.

For example, in a telephone bill it is necessary to print out a list of all connections, including the destination number, duration and cost of each call. This repeating row functionality can be achieved with so called blocks.

Blocks are simply regions of a document, which are repeated when createDocument() is called. In a block any number of block fields can be specified.

Blocks consist of two consecutive document targets with a unique name. The following screenshot illustrates these targets and their names in red:

< class="inlinemediaobject">

(» view larger).

The format of a block is as follows:

  1. blockStart_ + unique name
  2. blockEnd_ + unique name

For example:

  1. blockStart_block1
  2. blockEnd_block1

The content of a block is repeated, until all data assigned in the block fields has been injected into the template. The data for block fields is specified in PHP as a multi-assoc array.

The following screenshot of a template in Microsoft Word 2007 shows how block fields are used:

< class="inlinemediaobject">

Template, illustrating blocks in Microsoft Word 2007 (» view larger).

The following code populates the above template with data.

  1. $phpLiveDocx = new Zend_Service_LiveDocx_MailMerge();
  2.
  3. $phpLiveDocx->setUsername('myUsername')
  4.             ->setPassword('myPassword');
  5.
  6. $phpLiveDocx->setLocalTemplate('template.doc');
  7.
  8. $billConnections = array(
  9.     array(
  10.         'connection_number'   => '+49 421 335 912',
  11.         'connection_duration' => '00:00:07',
  12.         'fee'                 => '€ 0.03',
  13.     ),
  14.     array(
  15.         'connection_number'   => '+49 421 335 913',
  16.         'connection_duration' => '00:00:07',
  17.         'fee'                 => '€ 0.03',
  18.     ),
  19.     array(
  20.         'connection_number'   => '+49 421 335 914',
  21.         'connection_duration' => '00:00:07',
  22.         'fee'                 => '€ 0.03',
  23.     ),
  24.     array(
  25.         'connection_number'   => '+49 421 335 916',
  26.         'connection_duration' => '00:00:07',
  27.         'fee'                 => '€ 0.03',
  28.     ),
  29. );
  30.
  31. $phpLiveDocx->assign('connection', $billConnections);
  32.
  33. // ... assign other data here ...
  34.
  35. $phpLiveDocx->createDocument();
  36. $document = $phpLiveDocx->retrieveDocument('pdf');
  37. file_put_contents('document.pdf', $document);

The data, which is specified in the array $billConnections is repeated in the template in the block connection. The keys of the array (connection_number, connection_duration and fee) are the block field names - their data is inserted, one row per iteration.

The resulting document is written to disk in the file document.pdf. This file can now be post-processed, sent via e-mail or simply displayed, as is illustrated below in Document Viewer 2.26.1 on Ubuntu 9.04:

< class="inlinemediaobject">

Resulting document as PDF in Document Viewer 2.26.1 (» view larger).

You can download the DOC » template file and the resulting » PDF document.

NOTE: blocks may not be nested.

Generating bitmaps image files

In addition to document file formats, Zend_Service_LiveDocx_MailMerge also allows documents to be saved to a number of image file formats (BMP, GIF, JPG, PNG and TIFF). Each page of the document is saved to one file.

The following sample illustrates the use of getBitmaps($fromPage, $toPage, $zoomFactor, $format) and getAllBitmaps($zoomFactor, $format).

$fromPage is the lower-bound page number of the page range that should be returned as an image and $toPage the upper-bound page number. $zoomFactor is the size of the images, as a percent, relative to the original page size. The range of this parameter is 10 to 400. $format is the format of the images returned by this method. The supported formats can be obtained by calling getImageFormats().

  1. $date = new Zend_Date();
  2. $date->setLocale('en_US');
  3.
  4. $phpLiveDocx = new Zend_Service_LiveDocx_MailMerge();
  5.
  6. $phpLiveDocx->setUsername('myUsername')
  7.             ->setPassword('myPassword');
  8.
  9. $phpLiveDocx->setLocalTemplate('template.docx');
  10.
  11. $phpLiveDocx->assign('software', 'Magic Graphical Compression Suite v1.9')
  12.             ->assign('licensee', 'Daï Lemaitre')
  13.             ->assign('company',  'Megasoft Co-operation')
  14.             ->assign('date',     $date->get(Zend_Date::DATE_LONG))
  15.             ->assign('time',     $date->get(Zend_Date::TIME_LONG))
  16.             ->assign('city',     'Lyon')
  17.             ->assign('country',  'France');
  18.
  19. $phpLiveDocx->createDocument();
  20.
  21. // Get all bitmaps
  22. // (zoomFactor, format)
  23. $bitmaps = $phpLiveDocx->getAllBitmaps(100, 'png');
  24.
  25. // Get just bitmaps in specified range
  26. // (fromPage, toPage, zoomFactor, format)
  27. // $bitmaps = $phpLiveDocx->getBitmaps(2, 2, 100, 'png');
  28.
  29. foreach ($bitmaps as $pageNumber => $bitmapData) {
  30.     $filename = sprintf('documentPage%d.png', $pageNumber);
  31.     file_put_contents($filename, $bitmapData);
  32. }

This produces two files (documentPage1.png and documentPage2.png) and writes them to disk in the same directory as the executable PHP file.

< class="inlinemediaobject">

documentPage1.png (» view larger).

< class="inlinemediaobject">

documentPage2.png (» view larger).

Local vs. Remote Templates

Templates can be stored locally, on the client machine, or remotely, on the server. There are advantages and disadvantages to each approach.

In the case that a template is stored locally, it must be transfered from the client to the server on every request. If the content of the template rarely changes, this approach is inefficient. Similarly, if the template is several megabytes in size, it may take considerable time to transfer it to the server. Local template are useful in situations in which the content of the template is constantly changing.

The following code illustrates how to use a local template.

  1. $phpLiveDocx = new Zend_Service_LiveDocx_MailMerge();
  2.
  3. $phpLiveDocx->setUsername('myUsername')
  4.             ->setPassword('myPassword');
  5.
  6. $phpLiveDocx->setLocalTemplate('./template.docx');
  7.
  8. // assign data and create document

In the case that a template is stored remotely, it is uploaded once to the server and then simply referenced on all subsequent requests. Obviously, this is much quicker than using a local template, as the template does not have to be transfered on every request. For speed critical applications, it is recommended to use the remote template method.

The following code illustrates how to upload a template to the server:

  1. $phpLiveDocx = new Zend_Service_LiveDocx_MailMerge();
  2.
  3. $phpLiveDocx->setUsername('myUsername')
  4.             ->setPassword('myPassword');
  5.
  6. $phpLiveDocx->uploadTemplate('template.docx');

The following code illustrates how to reference the remotely stored template on all subsequent requests:

  1. $phpLiveDocx = new Zend_Service_LiveDocx_MailMerge();
  2.
  3. $phpLiveDocx->setUsername('myUsername')
  4.             ->setPassword('myPassword');
  5.
  6. $phpLiveDocx->setRemoteTemplate('template.docx');
  7.
  8. // assign data and create document

Getting Information

Zend_Service_LiveDocx_MailMerge provides a number of methods to get information on field names, available fonts and supported formats.

Example #1 Get Array of Field Names in Template

The following code returns and displays an array of all field names in the specified template. This functionality is useful, in the case that you create an application, in which an end-user can update a template.

  1. $phpLiveDocx = new Zend_Service_LiveDocx_MailMerge();
  2.
  3. $phpLiveDocx->setUsername('myUsername')
  4.             ->setPassword('myPassword');
  5.
  6. $templateName = 'template-1-text-field.docx';
  7. $phpLiveDocx->setLocalTemplate($templateName);
  8.
  9. $fieldNames = $phpLiveDocx->getFieldNames();
  10. foreach ($fieldNames as $fieldName) {
  11.     printf('- %s%s', $fieldName, PHP_EOL);
  12. }

Example #2 Get Array of Block Field Names in Template

The following code returns and displays an array of all block field names in the specified template. This functionality is useful, in the case that you create an application, in which an end-user can update a template. Before such templates can be populated, it is necessary to find out the names of the contained block fields.

  1. $phpLiveDocx = new Zend_Service_LiveDocx_MailMerge();
  2.
  3. $phpLiveDocx->setUsername('myUsername')
  4.             ->setPassword('myPassword');
  5.
  6. $templateName = 'template-block-fields.doc';
  7. $phpLiveDocx->setLocalTemplate($templateName);
  8.
  9. $blockNames = $phpLiveDocx->getBlockNames();
  10. foreach ($blockNames as $blockName) {
  11.     $blockFieldNames = $phpLiveDocx->getBlockFieldNames($blockName);
  12.     foreach ($blockFieldNames as $blockFieldName) {
  13.         printf('- %s::%s%s', $blockName, $blockFieldName, PHP_EOL);
  14.     }
  15. }

Example #3 Get Array of Fonts Installed on Server

The following code returns and displays an array of all fonts installed on the server. You can use this method to present a list of fonts which may be used in a template. It is important to inform the end-user about the fonts installed on the server, as only these fonts may be used in a template. In the case that a template contains fonts, which are not available on the server, font-substitution will take place. This may lead to undesirable results.

  1. $phpLiveDocx = new Zend_Service_LiveDocx_MailMerge();
  2.
  3. $phpLiveDocx->setUsername('myUsername')
  4.             ->setPassword('myPassword');
  5.
  6. Zend_Debug::dump($phpLiveDocx->getFontNames());

NOTE: As the return value of this method changes very infrequently, it is highly recommended to use a cache, such as Zend_Cache - this will considerably speed up your application.

Example #4 Get Array of Supported Template File Formats

The following code returns and displays an array of all supported template file formats. This method is particularly useful in the case that a combo list should be displayed that allows the end-user to select the input format of the documentation generation process.

  1. $phpLiveDocx = new Zend_Service_LiveDocx_MailMerge()
  2.
  3. $phpLiveDocx->setUsername('myUsername')
  4.             ->setPassword('myPassword');
  5.
  6. Zend_Debug::dump($phpLiveDocx->getTemplateFormats());

NOTE: As the return value of this method changes very infrequently, it is highly recommended to use a cache, such as Zend_Cache - this will considerably speed up your application.

Example #5 Get Array of Supported Document File Formats

The following code returns and displays an array of all supported document file formats. This method is particularly useful in the case that a combo list should be displayed that allows the end-user to select the output format of the documentation generation process.

  1. $phpLiveDocx = new Zend_Service_LiveDocx_MailMerge();
  2.
  3. $phpLiveDocx->setUsername('myUsername')
  4.             ->setPassword('myPassword');
  5.
  6. Zend_Debug::dump($phpLiveDocx->getDocumentFormats());

Example #6 Get Array of Supported Image File Formats

The following code returns and displays an array of all supported image file formats. This method is particularly useful in the case that a combo list should be displayed that allows the end-user to select the output format of the documentation generation process.

  1. $phpLiveDocx = new Zend_Service_LiveDocx_MailMerge();
  2.
  3. $phpLiveDocx->setUsername('myUsername')
  4.             ->setPassword('myPassword');
  5.
  6. Zend_Debug::dump($phpLiveDocx->getImageFormats());

NOTE: As the return value of this method changes very infrequently, it is highly recommended to use a cache, such as Zend_Cache - this will considerably speed up your application.

Zend_Service_Flickr
Zend_Service
Zend Framework手册 中文版
Zend_Service_Nirvanix
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Service
  • 简介
  • Zend_Service_Akismet
  • Zend_Service_Amazon
  • Zend_Service_Amazon_Ec2
  • Zend_Service_Amazon_Ec2: Instances
  • Zend_Service_Amazon_Ec2: Windows Instances
  • Zend_Service_Amazon_Ec2: Reserved Instances
  • Zend_Service_Amazon_Ec2: CloudWatch Monitoring
  • Zend_Service_Amazon_Ec2: Amazon Machine Images (AMI)
  • Zend_Service_Amazon_Ec2: Elastic Block Stroage (EBS)
  • Zend_Service_Amazon_Ec2: Elastic IP Addresses
  • Zend_Service_Amazon_Ec2: Keypairs
  • Zend_Service_Amazon_Ec2: Regions and Availability Zones
  • Zend_Service_Amazon_Ec2: Security Groups
  • Zend_Service_Amazon_S3
  • Zend_Service_Amazon_Sqs
  • Zend_Service_Audioscrobbler
  • Zend_Service_Delicious
  • Zend_Service_DeveloperGarden
  • Zend_Service_Flickr
  • Zend_Service_LiveDocx
  • Zend_Service_Nirvanix
  • Zend_Service_ReCaptcha
  • Zend_Service_Simpy
  • Introduction
  • Zend_Service_StrikeIron
  • Zend_Service_StrikeIron: Bundled Services
  • Zend_Service_StrikeIron: Advanced Uses
  • Zend_Service_Technorati
  • Zend_Service_Twitter
  • Zend_Service_WindowsAzure
  • Zend_Service_Yahoo


Zend_Service_Nirvanix - Zend Framework Manual

Zend_Service_LiveDocx
Zend_Service
Zend Framework手册 中文版
Zend_Service_ReCaptcha

Zend_Service_Nirvanix

Introduction

Nirvanix provides an Internet Media File System (IMFS), an Internet storage service that allows applications to upload, store and organize files and subsequently access them using a standard Web Services interface. An IMFS is distributed clustered file system, accessed over the Internet, and optimized for dealing with media files (audio, video, etc). The goal of an IMFS is to provide massive scalability to deal with the challenges of media storage growth, with guaranteed access and availability regardless of time and location. Finally, an IMFS gives applications the ability to access data securely, without the large fixed costs associated with acquiring and maintaining physical storage assets.

Registering with Nirvanix

Before you can get started with Zend_Service_Nirvanix, you must first register for an account. Please see the » Getting Started page on the Nirvanix website for more information.

After registering, you will receive a Username, Password, and Application Key. All three are required to use Zend_Service_Nirvanix.

API Documentation

Access to the Nirvanix IMFS is available through both SOAP and a faster REST service. Zend_Service_Nirvanix provides a relatively thin PHP 5 wrapper around the REST service.

Zend_Service_Nirvanix aims to make using the Nirvanix REST service easier but understanding the service itself is still essential to be successful with Nirvanix.

The » Nirvanix API Documentation provides an overview as well as detailed information using the service. Please familiarize yourself with this document and refer back to it as you use Zend_Service_Nirvanix.

Features

Nirvanix's REST service can be used effectively with PHP using the » SimpleXML extension and Zend_Http_Client alone. However, using it this way is somewhat inconvenient due to repetitive operations like passing the session token on every request and repeatedly checking the response body for error codes.

Zend_Service_Nirvanix provides the following functionality:

  • A single point for configuring your Nirvanix authentication credentials that can be used across the Nirvanix namespaces.

  • A proxy object that is more convenient to use than an HTTP client alone, mostly removing the need to manually construct HTTP POST requests to access the REST service.

  • A response wrapper that parses each response body and throws an exception if an error occurred, alleviating the need to repeatedly check the success of many commands.

  • Additional convenience methods for some of the more common operations.

Getting Started

Once you have registered with Nirvanix, you're ready to store your first file on the IMFS. The most common operations that you will need to do on the IMFS are creating a new file, downloading an existing file, and deleting a file. Zend_Service_Nirvanix provides convenience methods for these three operations.

  1. $auth = array('username' => 'your-username',
  2.               'password' => 'your-password',
  3.               'appKey'   => 'your-app-key');
  4.
  5. $nirvanix = new Zend_Service_Nirvanix($auth);
  6. $imfs = $nirvanix->getService('IMFS');
  7.
  8. $imfs->putContents('/foo.txt', 'contents to store');
  9.
  10. echo $imfs->getContents('/foo.txt');
  11.
  12. $imfs->unlink('/foo.txt');

The first step to using Zend_Service_Nirvanix is always to authenticate against the service. This is done by passing your credentials to the Zend_Service_Nirvanix constructor above. The associative array is passed directly to Nirvanix as POST parameters.

Nirvanix divides its web services into » namespaces. Each namespace encapsulates a group of related operations. After getting an instance of Zend_Service_Nirvanix, call the getService() method to create a proxy for the namespace you want to use. Above, a proxy for the IMFS namespace is created.

After you have a proxy for the namespace you want to use, call methods on it. The proxy will allow you to use any command available on the REST API. The proxy may also make convenience methods available, which wrap web service commands. The example above shows using the IMFS convenience methods to create a new file, retrieve and display that file, and finally delete the file.

Understanding the Proxy

In the previous example, we used the getService() method to return a proxy object to the IMFS namespace. The proxy object allows you to use the Nirvanix REST service in a way that's closer to making a normal PHP method call, as opposed to constructing your own HTTP request objects.

A proxy object may provide convenience methods. These are methods that the Zend_Service_Nirvanix provides to simplify the use of the Nirvanix web services. In the previous example, the methods putContents(), getContents(), and unlink() do not have direct equivalents in the REST API. They are convenience methods provided by Zend_Service_Nirvanix that abstract more complicated operations on the REST API.

For all other method calls to the proxy object, the proxy will dynamically convert the method call to the equivalent HTTP POST request to the REST API. It does this by using the method name as the API command, and an associative array in the first argument as the POST parameters.

Let's say you want to call the REST API method » RenameFile, which does not have a convenience method in Zend_Service_Nirvanix:

  1. $auth = array('username' => 'your-username',
  2.               'password' => 'your-password',
  3.               'appKey'   => 'your-app-key');
  4.
  5. $nirvanix = new Zend_Service_Nirvanix($auth);
  6. $imfs = $nirvanix->getService('IMFS');
  7.
  8. $result = $imfs->renameFile(array('filePath' => '/path/to/foo.txt',
  9.                                   'newFileName' => 'bar.txt'));

Above, a proxy for the IMFS namespace is created. A method, renameFile(), is then called on the proxy. This method does not exist as a convenience method in the PHP code, so it is trapped by __call() and converted into a POST request to the REST API where the associative array is used as the POST parameters.

Notice in the Nirvanix API documentation that sessionToken is required for this method but we did not give it to the proxy object. It is added automatically for your convenience.

The result of this operation will either be a Zend_Service_Nirvanix_Response object wrapping the XML returned by Nirvanix, or a Zend_Service_Nirvanix_Exception if an error occurred.

Examining Results

The Nirvanix REST API always returns its results in XML. Zend_Service_Nirvanix parses this XML with the SimpleXML extension and then decorates the resulting SimpleXMLElement with a Zend_Service_Nirvanix_Response object.

The simplest way to examine a result from the service is to use the built-in PHP functions like print_r():

  1. <?php
  2. $auth = array('username' => 'your-username',
  3.               'password' => 'your-password',
  4.               'appKey'   => 'your-app-key');
  5.
  6. $nirvanix = new Zend_Service_Nirvanix($auth);
  7. $imfs = $nirvanix->getService('IMFS');
  8.
  9. $result = $imfs->putContents('/foo.txt', 'fourteen bytes');
  10. print_r($result);
  11. ?>
  12.
  13. Zend_Service_Nirvanix_Response Object
  14. (
  15.     [_sxml:protected] => SimpleXMLElement Object
  16.         (
  17.             [ResponseCode] => 0
  18.             [FilesUploaded] => 1
  19.             [BytesUploaded] => 14
  20.         )
  21. )

You can access any property or method of the decorated SimpleXMLElement. In the above example, $result->BytesUploaded could be used to see the number of bytes received. Should you want to access the SimpleXMLElement directly, just use $result->getSxml().

The most common response from Nirvanix is success (ResponseCode of zero). It is not normally necessary to check ResponseCode because any non-zero result will throw a Zend_Service_Nirvanix_Exception. See the next section on handling errors.

Handling Errors

When using Nirvanix, it's important to anticipate errors that can be returned by the service and handle them appropriately.

All operations against the REST service result in an XML return payload that contains a ResponseCode element, such as the following example:

  1. <Response>
  2.    <ResponseCode>0</ResponseCode>
  3. </Response>

When the ResponseCode is zero such as in the example above, the operation was successful. When the operation is not successful, the ResponseCode is non-zero and an ErrorMessage element should be present.

To alleviate the need to repeatedly check if the ResponseCode is non-zero, Zend_Service_Nirvanix automatically checks each response returned by Nirvanix. If the ResponseCode indicates an error, a Zend_Service_Nirvanix_Exception will be thrown.

  1. $auth = array('username' => 'your-username',
  2.               'password' => 'your-password',
  3.               'appKey'   => 'your-app-key');
  4. $nirvanix = new Zend_Service_Nirvanix($auth);
  5.
  6. try {
  7.
  8.   $imfs = $nirvanix->getService('IMFS');
  9.   $imfs->unlink('/a-nonexistant-path');
  10.
  11. } catch (Zend_Service_Nirvanix_Exception $e) {
  12.   echo $e->getMessage() . "\n";
  13.   echo $e->getCode();
  14. }

In the example above, unlink() is a convenience method that wraps the DeleteFiles command on the REST API. The filePath parameter required by the » DeleteFiles command contains a path that does not exist. This will result in a Zend_Service_Nirvanix exception being thrown with the message "Invalid path" and code 70005.

The » Nirvanix API Documentation describes the errors associated with each command. Depending on your needs, you may wrap each command in a try block or wrap many commands in the same try block for convenience.

Zend_Service_LiveDocx
Zend_Service
Zend Framework手册 中文版
Zend_Service_ReCaptcha
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Service
  • 简介
  • Zend_Service_Akismet
  • Zend_Service_Amazon
  • Zend_Service_Amazon_Ec2
  • Zend_Service_Amazon_Ec2: Instances
  • Zend_Service_Amazon_Ec2: Windows Instances
  • Zend_Service_Amazon_Ec2: Reserved Instances
  • Zend_Service_Amazon_Ec2: CloudWatch Monitoring
  • Zend_Service_Amazon_Ec2: Amazon Machine Images (AMI)
  • Zend_Service_Amazon_Ec2: Elastic Block Stroage (EBS)
  • Zend_Service_Amazon_Ec2: Elastic IP Addresses
  • Zend_Service_Amazon_Ec2: Keypairs
  • Zend_Service_Amazon_Ec2: Regions and Availability Zones
  • Zend_Service_Amazon_Ec2: Security Groups
  • Zend_Service_Amazon_S3
  • Zend_Service_Amazon_Sqs
  • Zend_Service_Audioscrobbler
  • Zend_Service_Delicious
  • Zend_Service_DeveloperGarden
  • Zend_Service_Flickr
  • Zend_Service_LiveDocx
  • Zend_Service_Nirvanix
  • Zend_Service_ReCaptcha
  • Zend_Service_Simpy
  • Introduction
  • Zend_Service_StrikeIron
  • Zend_Service_StrikeIron: Bundled Services
  • Zend_Service_StrikeIron: Advanced Uses
  • Zend_Service_Technorati
  • Zend_Service_Twitter
  • Zend_Service_WindowsAzure
  • Zend_Service_Yahoo


Zend_Service_ReCaptcha - Zend Framework Manual

Zend_Service_Nirvanix
Zend_Service
Zend Framework手册 中文版
Zend_Service_Simpy

Zend_Service_ReCaptcha

Introduction

Zend_Service_ReCaptcha provides a client for the » reCAPTCHA Web Service. Per the reCAPTCHA site, "reCAPTCHA is a free CAPTCHA service that helps to digitize books." Each reCAPTCHA requires the user to input two words, the first of which is the actual CAPTCHA, and the second of which is a word from some scanned text that Optical Character Recognition (OCR) software has been unable to identify. The assumption is that if a user correctly provides the first word, the second is likely correctly entered as well, and can be used to improve OCR software for digitizing books.

In order to use the reCAPTCHA service, you will need to » sign up for an account and register one or more domains with the service in order to generate public and private keys.

Simplest use

Instantiate a Zend_Service_ReCaptcha object, passing it your public and private keys:

Example #1 Creating an instance of the reCAPTCHA service

  1. $recaptcha = new Zend_Service_ReCaptcha($pubKey, $privKey);

To render the reCAPTCHA, simply call the getHTML() method:

Example #2 Displaying the reCAPTCHA

  1. echo $recaptcha->getHTML();

When the form is submitted, you should receive two fields, 'recaptcha_challenge_field' and 'recaptcha_response_field'. Pass these to the reCAPTCHA object's verify() method:

Example #3 Verifying the form fields

  1. $result = $recaptcha->verify(
  2.     $_POST['recaptcha_challenge_field'],
  3.     $_POST['recaptcha_response_field']
  4. );

Once you have the result, test against it to see if it is valid. The result is a Zend_Service_ReCaptcha_Response object, which provides an isValid() method.

Example #4 Validating the reCAPTCHA

  1. if (!$result->isValid()) {
  2.     // Failed validation
  3. }

It is even simpler to use the reCAPTCHA Zend_Captcha adapter, or to use that adapter as a backend for the CAPTCHA form element. In each case, the details of rendering and validating the reCAPTCHA are automated for you.

Hiding email addresses

Zend_Service_ReCaptcha_MailHide can be used to hide email addresses. It will replace a part of an email address with a link that opens a popup window with a reCAPTCHA challenge. Solving the challenge will reveal the complete email address.

In order to use this component you will need » an account to generate public and private keys for the mailhide API.

Example #5 Using the mail hide component

  1. // The mail address we want to hide
  2. $mail = 'mail@example.com';
  3.
  4. // Create an instance of the mailhide component, passing it your public
  5. // and private keys, as well as the mail address you want to hide
  6. $mailHide = new Zend_Service_ReCaptcha_Mailhide();
  7. $mailHide->setPublicKey($pubKey);
  8. $mailHide->setPrivateKey($privKey);
  9. $mailHide->setEmail($mail);
  10.
  11. // Display it
  12. print($mailHide);

The example above will display "m...@example.com" where "..." has a link that opens up a popup window with a reCAPTCHA challenge.

The public key, private key, and the email address can also be specified in the constructor of the class. A fourth argument also exists that enables you to set some options for the component. The available options are listed in the following table:

Zend_Service_ReCaptcha_MailHide options
Option | Description | Expected Values | Default Value
linkTitle | The title attribute of the link | string | 'Reveal this e-mail address'
linkHiddenText | The text that includes the popup link | string | '...'
popupWidth | The width of the popup window | int | 500
popupHeight | The height of the popup window | int | 300

The configuration options can be set by sending them as the fourth argument to the constructor or by calling setOptions($options), which takes an associative array or an instance of Zend_Config.

Example #6 Generating many hidden email addresses

  1. // Create an instance of the mailhide component, passing it your public
  2. // and private keys, as well as some configuration options
  3. $mailHide = new Zend_Service_ReCaptcha_Mailhide();
  4. $mailHide->setPublicKey($pubKey);
  5. $mailHide->setPrivateKey($privKey);
  6. $mailHide->setOptions(array(
  7.     'linkTitle' => 'Click me',
  8.     'linkHiddenText' => '+++++',
  9. ));
  10.
  11. // The mail addresses we want to hide
  12. $mailAddresses = array(
  13.     'mail@example.com',
  14.     'johndoe@example.com',
  15.     'janedoe@example.com',
  16. );
  17.
  18. foreach ($mailAddresses as $mail) {
  19.     $mailHide->setEmail($mail);
  20.     print($mailHide);
  21. }
Zend_Service_Nirvanix
Zend_Service
Zend Framework手册 中文版
Zend_Service_Simpy
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Service
  • 简介
  • Zend_Service_Akismet
  • Zend_Service_Amazon
  • Zend_Service_Amazon_Ec2
  • Zend_Service_Amazon_Ec2: Instances
  • Zend_Service_Amazon_Ec2: Windows Instances
  • Zend_Service_Amazon_Ec2: Reserved Instances
  • Zend_Service_Amazon_Ec2: CloudWatch Monitoring
  • Zend_Service_Amazon_Ec2: Amazon Machine Images (AMI)
  • Zend_Service_Amazon_Ec2: Elastic Block Stroage (EBS)
  • Zend_Service_Amazon_Ec2: Elastic IP Addresses
  • Zend_Service_Amazon_Ec2: Keypairs
  • Zend_Service_Amazon_Ec2: Regions and Availability Zones
  • Zend_Service_Amazon_Ec2: Security Groups
  • Zend_Service_Amazon_S3
  • Zend_Service_Amazon_Sqs
  • Zend_Service_Audioscrobbler
  • Zend_Service_Delicious
  • Zend_Service_DeveloperGarden
  • Zend_Service_Flickr
  • Zend_Service_LiveDocx
  • Zend_Service_Nirvanix
  • Zend_Service_ReCaptcha
  • Zend_Service_Simpy
  • Introduction
  • Zend_Service_StrikeIron
  • Zend_Service_StrikeIron: Bundled Services
  • Zend_Service_StrikeIron: Advanced Uses
  • Zend_Service_Technorati
  • Zend_Service_Twitter
  • Zend_Service_WindowsAzure
  • Zend_Service_Yahoo


Zend_Service_Simpy - Zend Framework Manual

Zend_Service_ReCaptcha
Zend_Service
Zend Framework手册 中文版
Introduction

Zend_Service_Simpy

Introduction

Zend_Service_Simpy is a lightweight wrapper for the free REST API available for the Simpy social bookmarking service.

In order to use Zend_Service_Simpy, you should already have a Simpy account. To get an account, visit the » Simpy web site. For more information on the Simpy REST API, refer to the » Simpy REST API documentation.

The Simpy REST API allows developers to interact with specific aspects of the service that the Simpy web site offers. The sections following will outline the use of Zend_Service_Simpy for each of these areas.

  • Links: Create, Retrieve, Update, Delete

  • Tags: Retrieve, Delete, Rename, Merge, Split

  • Notes: Create, Retrieve, Update, Delete

  • Watchlists: Get, Get All

Links

When querying links, results are returned in descending order by date added. Links can be searched by title, nickname, tags, note, or even the content of the web page associated with the link. Simpy offers searching by any or all of these fields with phrases, boolean operators, and wildcards. See the » search syntax and » search fields sections of the Simpy FAQ for more information.

Example #1 Querying Links

  1. $simpy = new Zend_Service_Simpy('yourusername', 'yourpassword');
  2.
  3. /* Search for the 10 links added most recently */
  4. $linkQuery = new Zend_Service_Simpy_LinkQuery();
  5. $linkQuery->setLimit(10);
  6.
  7. /* Get and display the links */
  8. $linkSet = $simpy->getLinks($linkQuery);
  9. foreach ($linkSet as $link) {
  10.     echo '<a href="';
  11.     echo $link->getUrl();
  12.     echo '">';
  13.     echo $link->getTitle();
  14.     echo '</a><br />';
  15. }
  16.
  17. /* Search for the 5 links added most recently with 'PHP' in
  18. the title */
  19. $linkQuery->setQueryString('title:PHP');
  20. $linkQuery->setLimit(5);
  21.
  22. /* Search for all links with 'French' in the title and
  23. 'language' in the tags */
  24. $linkQuery->setQueryString('+title:French +tags:language');
  25.
  26. /* Search for all links with 'French' in the title and without
  27. 'travel' in the tags */
  28. $linkQuery->setQueryString('+title:French -tags:travel');
  29.
  30. /* Search for all links added on 12/9/06 */
  31. $linkQuery->setDate('2006-12-09');
  32.
  33. /* Search for all links added after 12/9/06 (excluding that
  34. date) */
  35. $linkQuery->setAfterDate('2006-12-09');
  36.
  37. /* Search for all links added before 12/9/06 (excluding that
  38. date) */
  39. $linkQuery->setBeforeDate('2006-12-09');
  40.
  41. /* Search for all links added between 12/1/06 and 12/9/06
  42. (excluding those two dates) */
  43. $linkQuery->setBeforeDate('2006-12-01');
  44. $linkQuery->setAfterDate('2006-12-09');

Links are represented uniquely by their URLs. In other words, if an attempt is made to save a link that has the same URL as an existing link, data for the existing link will be overwritten with the data specified in the save attempt.

Example #2 Modifying Links

  1. $simpy = new Zend_Service_Simpy('yourusername', 'yourpassword');
  2.
  3. /* Save a link */
  4. $simpy->saveLink(
  5.     'Zend Framework' // Title
  6.     'http://framework.zend.com', // URL
  7.     Zend_Service_Simpy_Link::ACCESSTYPE_PUBLIC, // Access Type
  8.     'zend, framework, php' // Tags
  9.     'Zend Framework home page' // Alternative title
  10.     'This site rocks!' // Note
  11. );
  12.
  13. /* Overwrite the existing link with new data */
  14. $simpy->saveLink(
  15.     'Zend Framework'
  16.     'http://framework.zend.com',
  17.     Zend_Service_Simpy_Link::ACCESSTYPE_PRIVATE, // Access Type has changed
  18.     'php, zend, framework' // Tags have changed order
  19.     'Zend Framework' // Alternative title has changed
  20.     'This site REALLY rocks!' // Note has changed
  21. );
  22.
  23. /* Delete the link */
  24. $simpy->deleteLink('http://framework.zend.com');
  25.
  26. /* A really easy way to do spring cleaning on your links ;) */
  27. $linkSet = $this->_simpy->getLinks();
  28. foreach ($linkSet as $link) {
  29.     $this->_simpy->deleteLink($link->getUrl());
  30. }

Tags

When retrieved, tags are sorted in decreasing order (i.e. highest first) by the number of links that use the tag.

Example #3 Working With Tags

  1. $simpy = new Zend_Service_Simpy('yourusername', 'yourpassword');
  2.
  3. /* Save a link with tags */
  4. $simpy->saveLink(
  5.     'Zend Framework' // Title
  6.     'http://framework.zend.com', // URL
  7.     Zend_Service_Simpy_Link::ACCESSTYPE_PUBLIC, // Access Type
  8.     'zend, framework, php' // Tags
  9. );
  10.
  11. /* Get a list of all tags in use by links and notes */
  12. $tagSet = $simpy->getTags();
  13.
  14. /* Display each tag with the number of links using it */
  15. foreach ($tagSet as $tag) {
  16.     echo $tag->getTag();
  17.     echo ' - ';
  18.     echo $tag->getCount();
  19.     echo '<br />';
  20. }
  21.
  22. /* Remove the 'zend' tag from all links using it */
  23. $simpy->removeTag('zend');
  24.
  25. /* Rename the 'framework' tag to 'frameworks' */
  26. $simpy->renameTag('framework', 'frameworks');
  27.
  28. /* Split the 'frameworks' tag into 'framework' and
  29. 'development', which will remove the 'frameworks' tag for
  30. all links that use it and add the tags 'framework' and
  31. 'development' to all of those links */
  32. $simpy->splitTag('frameworks', 'framework', 'development');
  33.
  34. /* Merge the 'framework' and 'development' tags back into
  35. 'frameworks', basically doing the opposite of splitting them */
  36. $simpy->mergeTags('framework', 'development', 'frameworks');

Notes

Notes can be saved, retrieved, and deleted. They are uniquely identified by a numeric ID value.

Example #4 Working With Notes

  1. $simpy = new Zend_Service_Simpy('yourusername', 'yourpassword');
  2.
  3. /* Save a note */
  4. $simpy->saveNote(
  5.     'Test Note', // Title
  6.     'test,note', // Tags
  7.     'This is a test note.' // Description
  8. );
  9.
  10. /* Overwrite an existing note */
  11. $simpy->saveNote(
  12.     'Updated Test Note', // Title
  13.     'test,note,updated', // Tags
  14.     'This is an updated test note.', // Description
  15.     $note->getId() // Unique identifier
  16. );
  17.
  18. /* Search for the 10 most recently added notes */
  19. $noteSet = $simpy->getNotes(null, 10);
  20.
  21. /* Display the notes */
  22. foreach ($noteSet as $note) {
  23.     echo '<p>';
  24.     echo $note->getTitle();
  25.     echo '<br />';
  26.     echo $note->getDescription();
  27.     echo '<br >';
  28.     echo $note->getTags();
  29.     echo '</p>';
  30. }
  31.
  32. /* Search for all notes with 'PHP' in the title */
  33. $noteSet = $simpy->getNotes('title:PHP');
  34.
  35. /* Search for all notes with 'PHP' in the title and
  36. without 'framework' in the description */
  37. $noteSet = $simpy->getNotes('+title:PHP -description:framework');
  38.
  39. /* Delete a note */
  40. $simpy->deleteNote($note->getId());

Watchlists

Watchlists cannot be created or removed using the API, only retrieved. Thus, you must set up a watchlist via the Simpy web site prior to attempting to access it using the API.

Example #5 Retrieving Watchlists

  1. $simpy = new Zend_Service_Simpy('yourusername', 'yourpassword');
  2.
  3. /* Get a list of all watchlists */
  4. $watchlistSet = $simpy->getWatchlists();
  5.
  6. /* Display data for each watchlist */
  7. foreach ($watchlistSet as $watchlist) {
  8.     echo $watchlist->getId();
  9.     echo '<br />';
  10.     echo $watchlist->getName();
  11.     echo '<br />';
  12.     echo $watchlist->getDescription();
  13.     echo '<br />';
  14.     echo $watchlist->getAddDate();
  15.     echo '<br />';
  16.     echo $watchlist->getNewLinks();
  17.     echo '<br />';
  18.
  19.     foreach ($watchlist->getUsers() as $user) {
  20.         echo $user;
  21.         echo '<br />';
  22.     }
  23.
  24.     foreach ($watchlist->getFilters() as $filter) {
  25.         echo $filter->getName();
  26.         echo '<br />';
  27.         echo $filter->getQuery();
  28.         echo '<br />';
  29.     }
  30. }
  31.
  32. /* Get an individual watchlist by its identifier */
  33. $watchlist = $simpy->getWatchlist($watchlist->getId());
  34. $watchlist = $simpy->getWatchlist(1);
Zend_Service_ReCaptcha
Zend_Service
Zend Framework手册 中文版
Introduction
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Service
  • 简介
  • Zend_Service_Akismet
  • Zend_Service_Amazon
  • Zend_Service_Amazon_Ec2
  • Zend_Service_Amazon_Ec2: Instances
  • Zend_Service_Amazon_Ec2: Windows Instances
  • Zend_Service_Amazon_Ec2: Reserved Instances
  • Zend_Service_Amazon_Ec2: CloudWatch Monitoring
  • Zend_Service_Amazon_Ec2: Amazon Machine Images (AMI)
  • Zend_Service_Amazon_Ec2: Elastic Block Stroage (EBS)
  • Zend_Service_Amazon_Ec2: Elastic IP Addresses
  • Zend_Service_Amazon_Ec2: Keypairs
  • Zend_Service_Amazon_Ec2: Regions and Availability Zones
  • Zend_Service_Amazon_Ec2: Security Groups
  • Zend_Service_Amazon_S3
  • Zend_Service_Amazon_Sqs
  • Zend_Service_Audioscrobbler
  • Zend_Service_Delicious
  • Zend_Service_DeveloperGarden
  • Zend_Service_Flickr
  • Zend_Service_LiveDocx
  • Zend_Service_Nirvanix
  • Zend_Service_ReCaptcha
  • Zend_Service_Simpy
  • Introduction
  • Zend_Service_StrikeIron
  • Zend_Service_StrikeIron: Bundled Services
  • Zend_Service_StrikeIron: Advanced Uses
  • Zend_Service_Technorati
  • Zend_Service_Twitter
  • Zend_Service_WindowsAzure
  • Zend_Service_Yahoo


Introduction - Zend Framework Manual

Zend_Service_Simpy
Zend_Service
Zend Framework手册 中文版
Zend_Service_StrikeIron

Introduction

The Zend_Service_SlideShare component is used to interact with the » slideshare.net web services for hosting slide shows online. With this component, you can embed slide shows which are hosted on this web site within a web site and even upload new slide shows to your account.

Getting Started with Zend_Service_SlideShare

In order to use the Zend_Service_SlideShare component you must first create an account on the slideshare.net servers (more information can be found » here) in order to receive an API key, username, password and shared secret value -- all of which are needed in order to use the Zend_Service_SlideShare component.

Once you have setup an account, you can begin using the Zend_Service_SlideShare component by creating a new instance of the Zend_Service_SlideShare object and providing these values as shown below:

  1. // Create a new instance of the component
  2. $ss = new Zend_Service_SlideShare('APIKEY',
  3.                                   'SHAREDSECRET',
  4.                                   'USERNAME',
  5.                                   'PASSWORD');

The SlideShow object

All slide shows in the Zend_Service_SlideShare component are represented using the Zend_Service_SlideShare_SlideShow object (both when retrieving and uploading new slide shows). For your reference a pseudo-code version of this class is provided below.

  1. class Zend_Service_SlideShare_SlideShow {
  2.
  3.     /**
  4.      * Retrieves the location of the slide show
  5.      */
  6.     public function getLocation() {
  7.         return $this->_location;
  8.     }
  9.
  10.     /**
  11.      * Gets the transcript for this slide show
  12.      */
  13.     public function getTranscript() {
  14.         return $this->_transcript;
  15.     }
  16.
  17.     /**
  18.      * Adds a tag to the slide show
  19.      */
  20.     public function addTag($tag) {
  21.         $this->_tags[] = (string)$tag;
  22.         return $this;
  23.     }
  24.
  25.     /**
  26.      * Sets the tags for the slide show
  27.      */
  28.     public function setTags(Array $tags) {
  29.         $this->_tags = $tags;
  30.         return $this;
  31.     }
  32.
  33.     /**
  34.      * Gets all of the tags associated with the slide show
  35.      */
  36.     public function getTags() {
  37.         return $this->_tags;
  38.     }
  39.
  40.     /**
  41.      * Sets the filename on the local filesystem of the slide show
  42.      * (for uploading a new slide show)
  43.      */
  44.     public function setFilename($file) {
  45.         $this->_slideShowFilename = (string)$file;
  46.         return $this;
  47.     }
  48.
  49.     /**
  50.      * Retrieves the filename on the local filesystem of the slide show
  51.      * which will be uploaded
  52.      */
  53.     public function getFilename() {
  54.         return $this->_slideShowFilename;
  55.     }
  56.
  57.     /**
  58.      * Gets the ID for the slide show
  59.      */
  60.     public function getId() {
  61.         return $this->_slideShowId;
  62.     }
  63.
  64.     /**
  65.      * Retrieves the HTML embed code for the slide show
  66.      */
  67.     public function getEmbedCode() {
  68.         return $this->_embedCode;
  69.     }
  70.
  71.     /**
  72.      * Retrieves the Thumbnail URi for the slide show
  73.      */
  74.     public function getThumbnailUrl() {
  75.         return $this->_thumbnailUrl;
  76.     }
  77.
  78.     /**
  79.      * Sets the title for the Slide show
  80.      */
  81.     public function setTitle($title) {
  82.         $this->_title = (string)$title;
  83.         return $this;
  84.     }
  85.
  86.     /**
  87.      * Retrieves the Slide show title
  88.      */
  89.     public function getTitle() {
  90.         return $this->_title;
  91.     }
  92.
  93.     /**
  94.      * Sets the description for the Slide show
  95.      */
  96.     public function setDescription($desc) {
  97.         $this->_description = (string)$desc;
  98.         return $this;
  99.     }
  100.
  101.     /**
  102.      * Gets the description of the slide show
  103.      */
  104.     public function getDescription() {
  105.         return $this->_description;
  106.     }
  107.
  108.     /**
  109.      * Gets the numeric status of the slide show on the server
  110.      */
  111.     public function getStatus() {
  112.         return $this->_status;
  113.     }
  114.
  115.     /**
  116.      * Gets the textual description of the status of the slide show on
  117.      * the server
  118.      */
  119.     public function getStatusDescription() {
  120.         return $this->_statusDescription;
  121.     }
  122.
  123.     /**
  124.      * Gets the permanent link of the slide show
  125.      */
  126.     public function getPermaLink() {
  127.         return $this->_permalink;
  128.     }
  129.
  130.     /**
  131.      * Gets the number of views the slide show has received
  132.      */
  133.     public function getNumViews() {
  134.         return $this->_numViews;
  135.     }
  136. }

Note: The above pseudo-class only shows those methods which should be used by end-user developers. Other available methods are internal to the component.

When using the Zend_Service_SlideShare component, this data class will be used frequently to browse or add new slide shows to or from the web service.

Retrieving a single slide show

The simplest usage of the Zend_Service_SlideShare component is the retrieval of a single slide show by slide show ID provided by the slideshare.net application and is done by calling the getSlideShow() method of a Zend_Service_SlideShare object and using the resulting Zend_Service_SlideShare_SlideShow object as shown.

  1. // Create a new instance of the component
  2. $ss = new Zend_Service_SlideShare('APIKEY',
  3.                                   'SHAREDSECRET',
  4.                                   'USERNAME',
  5.                                   'PASSWORD');
  6.
  7. $slideshow = $ss->getSlideShow(123456);
  8.
  9. print "Slide Show Title: {$slideshow->getTitle()}<br/>\n";
  10. print "Number of views: {$slideshow->getNumViews()}<br/>\n";

Retrieving Groups of Slide Shows

If you do not know the specific ID of a slide show you are interested in retrieving, you can retrieving groups of slide shows by using one of three methods:

  • Slide shows from a specific account

    You can retrieve slide shows from a specific account by using the getSlideShowsByUsername() method and providing the username from which the slide shows should be retrieved

  • Slide shows which contain specific tags

    You can retrieve slide shows which contain one or more specific tags by using the getSlideShowsByTag method and providing one or more tags which the slide show must have assigned to it in order to be retrieved

  • Slide shows by group

    You can retrieve slide shows which are a member of a specific group using the getSlideShowsByGroup method and providing the name of the group which the slide show must belong to in order to be retrieved

Each of the above methods of retrieving multiple slide shows a similar approach is used. An example of using each method is shown below:

  1. // Create a new instance of the component
  2. $ss = new Zend_Service_SlideShare('APIKEY',
  3.                                   'SHAREDSECRET',
  4.                                   'USERNAME',
  5.                                   'PASSWORD');
  6.
  7. $starting_offset = 0;
  8. $limit = 10;
  9.
  10. // Retrieve the first 10 of each type
  11. $ss_user = $ss->getSlideShowsByUser('username', $starting_offset, $limit);
  12. $ss_tags = $ss->getSlideShowsByTag('zend', $starting_offset, $limit);
  13. $ss_group = $ss->getSlideShowsByGroup('mygroup', $starting_offset, $limit);
  14.
  15. // Iterate over the slide shows
  16. foreach($ss_user as $slideshow) {
  17.    print "Slide Show Title: {$slideshow->getTitle}<br/>\n";
  18. }

Zend_Service_SlideShare Caching policies

By default, Zend_Service_SlideShare will cache any request against the web service automatically to the filesystem (default path /tmp) for 12 hours. If you desire to change this behavior, you must provide your own Zend_Cache object using the setCacheObject method as shown:

  1. $frontendOptions = array(
  2.                         'lifetime' => 7200,
  3.                         'automatic_serialization' => true);
  4. $backendOptions  = array(
  5.                         'cache_dir' => '/webtmp/');
  6.
  7. $cache = Zend_Cache::factory('Core',
  8.                              'File',
  9.                              $frontendOptions,
  10.                              $backendOptions);
  11.
  12. $ss = new Zend_Service_SlideShare('APIKEY',
  13.                                   'SHAREDSECRET',
  14.                                   'USERNAME',
  15.                                   'PASSWORD');
  16. $ss->setCacheObject($cache);
  17.
  18. $ss_user = $ss->getSlideShowsByUser('username', $starting_offset, $limit);

Changing the behavior of the HTTP Client

If for whatever reason you would like to change the behavior of the HTTP client when making the web service request, you can do so by creating your own instance of the Zend_Http_Client object (see Zend_Http). This is useful for instance when it is desirable to set the timeout for the connection to something other then default as shown:

  1. $client = new Zend_Http_Client();
  2. $client->setConfig(array('timeout' => 5));
  3.
  4. $ss = new Zend_Service_SlideShare('APIKEY',
  5.                                   'SHAREDSECRET',
  6.                                   'USERNAME',
  7.                                   'PASSWORD');
  8. $ss->setHttpClient($client);
  9. $ss_user = $ss->getSlideShowsByUser('username', $starting_offset, $limit);
Zend_Service_Simpy
Zend_Service
Zend Framework手册 中文版
Zend_Service_StrikeIron
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Service
  • 简介
  • Zend_Service_Akismet
  • Zend_Service_Amazon
  • Zend_Service_Amazon_Ec2
  • Zend_Service_Amazon_Ec2: Instances
  • Zend_Service_Amazon_Ec2: Windows Instances
  • Zend_Service_Amazon_Ec2: Reserved Instances
  • Zend_Service_Amazon_Ec2: CloudWatch Monitoring
  • Zend_Service_Amazon_Ec2: Amazon Machine Images (AMI)
  • Zend_Service_Amazon_Ec2: Elastic Block Stroage (EBS)
  • Zend_Service_Amazon_Ec2: Elastic IP Addresses
  • Zend_Service_Amazon_Ec2: Keypairs
  • Zend_Service_Amazon_Ec2: Regions and Availability Zones
  • Zend_Service_Amazon_Ec2: Security Groups
  • Zend_Service_Amazon_S3
  • Zend_Service_Amazon_Sqs
  • Zend_Service_Audioscrobbler
  • Zend_Service_Delicious
  • Zend_Service_DeveloperGarden
  • Zend_Service_Flickr
  • Zend_Service_LiveDocx
  • Zend_Service_Nirvanix
  • Zend_Service_ReCaptcha
  • Zend_Service_Simpy
  • Introduction
  • Zend_Service_StrikeIron
  • Zend_Service_StrikeIron: Bundled Services
  • Zend_Service_StrikeIron: Advanced Uses
  • Zend_Service_Technorati
  • Zend_Service_Twitter
  • Zend_Service_WindowsAzure
  • Zend_Service_Yahoo


Zend_Service_StrikeIron - Zend Framework Manual

Introduction
Zend_Service
Zend Framework手册 中文版
Zend_Service_StrikeIron: Bundled Services

Zend_Service_StrikeIron

Zend_Service_StrikeIron provides a PHP 5 client to StrikeIron web services. See the following sections:

  • Zend_Service_StrikeIron

  • Zend_Service_StrikeIron: Bundled Services

  • Zend_Service_StrikeIron: Advanced Uses

Overview

» StrikeIron offers hundreds of commercial data services ("Data as a Service") such as Online Sales Tax, Currency Rates, Stock Quotes, Geocodes, Global Address Verification, Yellow/White Pages, MapQuest Driving Directions, Dun & Bradstreet Business Credit Checks, and much, much more.

Each StrikeIron web service shares a standard SOAP (and REST) API, making it easy to integrate and manage multiple services. StrikeIron also manages customer billing for all services in a single account, making it perfect for solution providers. Get started with free web services at » http://www.strikeiron.com/sdp.

StrikeIron's services may be used through the » PHP 5 SOAP extension alone. However, using StrikeIron this way does not give an ideal PHP-like interface. The Zend_Service_StrikeIron component provides a lightweight layer on top of the SOAP extension for working with StrikeIron services in a more convenient, PHP-like manner.

Note: The PHP 5 SOAP extension must be installed and enabled to use Zend_Service_StrikeIron.

The Zend_Service_StrikeIron component provides:

  • A single point for configuring your StrikeIron authentication credentials that can be used across many StrikeIron services.

  • A standard way of retrieving your StrikeIron subscription information such as license status and the number of hits remaining to a service.

  • The ability to use any StrikeIron service from its WSDL without creating a PHP wrapper class, and the option of creating a wrapper for a more convenient interface.

  • Wrappers for three popular StrikeIron services.

Registering with StrikeIron

Before you can get started with Zend_Service_StrikeIron, you must first » register for a StrikeIron developer account.

After registering, you will receive a StrikeIron username and password. These will be used when connecting to StrikeIron using Zend_Service_StrikeIron.

You will also need to » sign up for StrikeIron's Super Data Pack Web Service.

Both registration steps are free and can be done relatively quickly through the StrikeIron website.

Getting Started

Once you have » registered for a StrikeIron account and signed up for the » Super Data Pack, you're ready to start using Zend_Service_StrikeIron.

StrikeIron consists of hundreds of different web services. Zend_Service_StrikeIron can be used with many of these services but provides supported wrappers for three of them:

  • ZIP Code Information

  • US Address Verification

  • Sales & Use Tax Basic

The class Zend_Service_StrikeIron provides a simple way of specifying your StrikeIron account information and other options in its constructor. It also has a factory method that will return clients for StrikeIron services:

  1. $strikeIron = new Zend_Service_StrikeIron(array('username' => 'your-username',
  2.                                                 'password' => 'your-password'));
  3.
  4. $taxBasic = $strikeIron->getService(array('class' => 'SalesUseTaxBasic'));

The getService() method will return a client for any StrikeIron service by the name of its PHP wrapper class. In this case, the name SalesUseTaxBasic refers to the wrapper class Zend_Service_StrikeIron_SalesUseTaxBasic. Wrappers are included for three services and described in Bundled Services.

The getService() method can also return a client for a StrikeIron service that does not yet have a PHP wrapper. This is explained in Using Services by WSDL.

Making Your First Query

Once you have used the getService() method to get a client for a particular StrikeIron service, you can utilize that client by calling methods on it just like any other PHP object.

  1. $strikeIron = new Zend_Service_StrikeIron(array('username' => 'your-username',
  2.                                                 'password' => 'your-password'));
  3.
  4. // Get a client for the Sales & Use Tax Basic service
  5. $taxBasic = $strikeIron->getService(array('class' => 'SalesUseTaxBasic'));
  6.
  7. // Query tax rate for Ontario, Canada
  8. $rateInfo = $taxBasic->getTaxRateCanada(array('province' => 'ontario'));
  9. echo $rateInfo->province;
  10. echo $rateInfo->abbreviation;
  11. echo $rateInfo->GST;
In the example above, the getService() method is used to return a client to the Sales & Use Tax Basic service. The client object is stored in $taxBasic.

The getTaxRateCanada() method is then called on the service. An associative array is used to supply keyword parameters to the method. This is the way that all StrikeIron methods are called.

The result from getTaxRateCanada() is stored in $rateInfo and has properties like province and GST.

Many of the StrikeIron services are as simple to use as the example above. See Bundled Services for detailed information on three StrikeIron services.

Examining Results

When learning or debugging the StrikeIron services, it's often useful to dump the result returned from a method call. The result will always be an object that is an instance of Zend_Service_StrikeIron_Decorator. This is a small » decorator object that wraps the results from the method call.

The simplest way to examine a result from the service is to use the built-in PHP functions like » print_r():

  1. <?php
  2. $strikeIron = new Zend_Service_StrikeIron(array('username' => 'your-username',
  3.                                                 'password' => 'your-password'));
  4.
  5. $taxBasic = $strikeIron->getService(array('class' => 'SalesUseTaxBasic'));
  6.
  7. $rateInfo = $taxBasic->getTaxRateCanada(array('province' => 'ontario'));
  8. print_r($rateInfo);
  9. ?>
  10.
  11. Zend_Service_StrikeIron_Decorator Object
  12. (
  13.     [_name:protected] => GetTaxRateCanadaResult
  14.     [_object:protected] => stdClass Object
  15.         (
  16.             [abbreviation] => ON
  17.             [province] => ONTARIO
  18.             [GST] => 0.06
  19.             [PST] => 0.08
  20.             [total] => 0.14
  21.             [HST] => Y
  22.         )
  23. )

In the output above, we see that the decorator ($rateInfo) wraps an object named GetTaxRateCanadaResult, the result of the call to getTaxRateCanada().

This means that $rateInfo has public properties like abbreviation, province, and GST. These are accessed like $rateInfo->province.

Tip

StrikeIron result properties sometimes start with an uppercase letter such as Foo or Bar where most PHP object properties normally start with a lowercase letter as in foo or bar. The decorator will automatically do this inflection so you may read a property Foo as foo.

If you ever need to get the original object or its name out of the decorator, use the respective methods getDecoratedObject() and getDecoratedObjectName().

Handling Errors

The previous examples are naive, i.e. no error handling was shown. It's possible that StrikeIron will return a fault during a method call. Events like bad account credentials or an expired subscription can cause StrikeIron to raise a fault.

An exception will be thrown when such a fault occurs. You should anticipate and catch these exceptions when making method calls to the service:

  1. $strikeIron = new Zend_Service_StrikeIron(array('username' => 'your-username',
  2.                                                 'password' => 'your-password'));
  3.
  4. $taxBasic = $strikeIron->getService(array('class' => 'SalesUseTaxBasic'));
  5.
  6. try {
  7.
  8.   $taxBasic->getTaxRateCanada(array('province' => 'ontario'));
  9.
  10. } catch (Zend_Service_StrikeIron_Exception $e) {
  11.
  12.   // error handling for events like connection
  13.   // problems or subscription errors
  14.
  15. }
The exceptions thrown will always be Zend_Service_StrikeIron_Exception.

It's important to understand the difference between exceptions and normal failed method calls. Exceptions occur for exceptional conditions, such as the network going down or your subscription expiring. Failed method calls that are a common occurrence, such as getTaxRateCanada() not finding the province you supplied, will not result an in exception.

Note: Every time you make a method call to a StrikeIron service, you should check the response object for validity and also be prepared to catch an exception.

Checking Your Subscription

StrikeIron provides many different services. Some of these are free, some are available on a trial basis, and some are pay subscription only. When using StrikeIron, it's important to be aware of your subscription status for the services you are using and check it regularly.

Each StrikeIron client returned by the getService method has the ability to check the subscription status for that service using the getSubscriptionInfo() method of the client:

  1. // Get a client for the Sales & Use Tax Basic service
  2. $strikeIron = new Zend_Service_StrikeIron(array('username' => 'your-username',
  3.                                                 'password' => 'your-password'));
  4.
  5. $taxBasic = $strikeIron->getService(array('class => 'SalesUseTaxBasic'));
  6.
  7. // Check remaining hits for the Sales & Use Tax Basic service
  8. $subscription = $taxBasic->getSubscriptionInfo();
  9. echo $subscription->remainingHits;

The getSubscriptionInfo() method will return an object that typically has a remainingHits property. It's important to check the status on each service that you are using. If a method call is made to StrikeIron after the remaining hits have been used up, an exception will occur.

Checking your subscription to a service does not use any remaining hits to the service. Each time any method call to the service is made, the number of hits remaining will be cached and this cached value will be returned by getSubscriptionInfo() without connecting to the service again. To force getSubscriptionInfo() to override its cache and query the subscription information again, use getSubscriptionInfo(true).

Introduction
Zend_Service
Zend Framework手册 中文版
Zend_Service_StrikeIron: Bundled Services
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Service
  • 简介
  • Zend_Service_Akismet
  • Zend_Service_Amazon
  • Zend_Service_Amazon_Ec2
  • Zend_Service_Amazon_Ec2: Instances
  • Zend_Service_Amazon_Ec2: Windows Instances
  • Zend_Service_Amazon_Ec2: Reserved Instances
  • Zend_Service_Amazon_Ec2: CloudWatch Monitoring
  • Zend_Service_Amazon_Ec2: Amazon Machine Images (AMI)
  • Zend_Service_Amazon_Ec2: Elastic Block Stroage (EBS)
  • Zend_Service_Amazon_Ec2: Elastic IP Addresses
  • Zend_Service_Amazon_Ec2: Keypairs
  • Zend_Service_Amazon_Ec2: Regions and Availability Zones
  • Zend_Service_Amazon_Ec2: Security Groups
  • Zend_Service_Amazon_S3
  • Zend_Service_Amazon_Sqs
  • Zend_Service_Audioscrobbler
  • Zend_Service_Delicious
  • Zend_Service_DeveloperGarden
  • Zend_Service_Flickr
  • Zend_Service_LiveDocx
  • Zend_Service_Nirvanix
  • Zend_Service_ReCaptcha
  • Zend_Service_Simpy
  • Introduction
  • Zend_Service_StrikeIron
  • Zend_Service_StrikeIron: Bundled Services
  • Zend_Service_StrikeIron: Advanced Uses
  • Zend_Service_Technorati
  • Zend_Service_Twitter
  • Zend_Service_WindowsAzure
  • Zend_Service_Yahoo


Zend_Service_StrikeIron: Advanced Uses - Zend Framework Manual

Zend_Service_StrikeIron: Bundled Services
Zend_Service
Zend Framework手册 中文版
Zend_Service_Technorati

Zend_Service_StrikeIron: Advanced Uses

This section describes the more advanced uses of Zend_Service_StrikeIron.

Using Services by WSDL

Some StrikeIron services may have a PHP wrapper class available, such as those described in Bundled Services. However, StrikeIron offers hundreds of services and many of these may be usable even without creating a special wrapper class.

To try a StrikeIron service that does not have a wrapper class available, give the wsdl option to getService() instead of the class option:

  1. $strikeIron = new Zend_Service_StrikeIron(array('username' => 'your-username',
  2.                                                 'password' => 'your-password'));
  3.
  4. // Get a generic client to the Reverse Phone Lookup service
  5. $phone = $strikeIron->getService(
  6.     array('wsdl' => 'http://ws.strikeiron.com/ReversePhoneLookup?WSDL')
  7. );
  8.
  9. $result = $phone->lookup(array('Number' => '(408) 253-8800'));
  10. echo $result->listingName;
  11.
  12. // Zend Technologies USA Inc

Using StrikeIron services from the WSDL will require at least some understanding of the WSDL files. StrikeIron has many resources on its site to help with this. Also, » Jan Schneider from the » Horde project has written a » small PHP routine that will format a WSDL file into more readable HTML.

Please note that only the services described in the Bundled Services section are officially supported.

Viewing SOAP Transactions

All communication with StrikeIron is done using the SOAP extension. It is sometimes useful to view the XML exchanged with StrikeIron for debug purposes.

Every StrikeIron client (subclass of Zend_Service_StrikeIron_Base) contains a getSoapClient() method to return the underlying instance of SOAPClient used to communicate with StrikeIron.

PHP's » SOAPClient has a trace option that causes it to remember the XML exchanged during the last transaction. Zend_Service_StrikeIron does not enable the trace option by default but this can easily by changed by specifying the options that will be passed to the SOAPClient constructor.

To view a SOAP transaction, call the getSoapClient() method to get the SOAPClient instance and then call the appropriate methods like » __getLastRequest() and » __getLastRequest():

  1. $strikeIron =
  2.     new Zend_Service_StrikeIron(array('username' => 'your-username',
  3.                                       'password' => 'your-password',
  4.                                       'options'  => array('trace' => true)));
  5.
  6. // Get a client for the Sales & Use Tax Basic service
  7. $taxBasic = $strikeIron->getService(array('class' => 'SalesUseTaxBasic'));
  8.
  9. // Perform a method call
  10. $taxBasic->getTaxRateCanada(array('province' => 'ontario'));
  11.
  12. // Get SOAPClient instance and view XML
  13. $soapClient = $taxBasic->getSoapClient();
  14. echo $soapClient->__getLastRequest();
  15. echo $soapClient->__getLastResponse();

Zend_Service_StrikeIron: Bundled Services
Zend_Service
Zend Framework手册 中文版
Zend_Service_Technorati
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Service
  • 简介
  • Zend_Service_Akismet
  • Zend_Service_Amazon
  • Zend_Service_Amazon_Ec2
  • Zend_Service_Amazon_Ec2: Instances
  • Zend_Service_Amazon_Ec2: Windows Instances
  • Zend_Service_Amazon_Ec2: Reserved Instances
  • Zend_Service_Amazon_Ec2: CloudWatch Monitoring
  • Zend_Service_Amazon_Ec2: Amazon Machine Images (AMI)
  • Zend_Service_Amazon_Ec2: Elastic Block Stroage (EBS)
  • Zend_Service_Amazon_Ec2: Elastic IP Addresses
  • Zend_Service_Amazon_Ec2: Keypairs
  • Zend_Service_Amazon_Ec2: Regions and Availability Zones
  • Zend_Service_Amazon_Ec2: Security Groups
  • Zend_Service_Amazon_S3
  • Zend_Service_Amazon_Sqs
  • Zend_Service_Audioscrobbler
  • Zend_Service_Delicious
  • Zend_Service_DeveloperGarden
  • Zend_Service_Flickr
  • Zend_Service_LiveDocx
  • Zend_Service_Nirvanix
  • Zend_Service_ReCaptcha
  • Zend_Service_Simpy
  • Introduction
  • Zend_Service_StrikeIron
  • Zend_Service_StrikeIron: Bundled Services
  • Zend_Service_StrikeIron: Advanced Uses
  • Zend_Service_Technorati
  • Zend_Service_Twitter
  • Zend_Service_WindowsAzure
  • Zend_Service_Yahoo


Zend_Service_StrikeIron: Bundled Services - Zend Framework Manual

Zend_Service_StrikeIron
Zend_Service
Zend Framework手册 中文版
Zend_Service_StrikeIron: Advanced Uses

Zend_Service_StrikeIron: Bundled Services

Zend_Service_StrikeIron comes with wrapper classes for three popular StrikeIron services.

ZIP Code Information

Zend_Service_StrikeIron_ZipCodeInfo provides a client for StrikeIron's Zip Code Information Service. For more information on this service, visit these StrikeIron resources:

  • » Zip Code Information Service Page

  • » Zip Code Information Service WSDL

The service contains a getZipCode() method that will retrieve information about a United States ZIP code or Canadian postal code:
  1. $strikeIron = new Zend_Service_StrikeIron(array('username' => 'your-username',
  2.                                                 'password' => 'your-password'));
  3.
  4. // Get a client for the Zip Code Information service
  5. $zipInfo = $strikeIron->getService(array('class' => 'ZipCodeInfo'));
  6.
  7. // Get the Zip information for 95014
  8. $response = $zipInfo->getZipCode(array('ZipCode' => 95014));
  9. $zips = $response->serviceResult;
  10.
  11. // Display the results
  12. if ($zips->count == 0) {
  13.     echo 'No results found';
  14. } else {
  15.     // a result with one single zip code is returned as an object,
  16.     // not an array with one element as one might expect.
  17.     if (! is_array($zips->zipCodes)) {
  18.         $zips->zipCodes = array($zips->zipCodes);
  19.     }
  20.
  21.     // print all of the possible results
  22.     foreach ($zips->zipCodes as $z) {
  23.         $info = $z->zipCodeInfo;
  24.
  25.         // show all properties
  26.         print_r($info);
  27.
  28.         // or just the city name
  29.         echo $info->preferredCityName;
  30.     }
  31. }
  32.
  33. // Detailed status information
  34. // http://www.strikeiron.com/exampledata/StrikeIronZipCodeInformation_v3.pdf
  35. $status = $response->serviceStatus;

U.S. Address Verification

Zend_Service_StrikeIron_USAddressVerification provides a client for StrikeIron's U.S. Address Verification Service. For more information on this service, visit these StrikeIron resources:

  • » U.S. Address Verification Service Page

  • » U.S. Address Verification Service WSDL

The service contains a verifyAddressUSA() method that will verify an address in the United States:

  1. $strikeIron = new Zend_Service_StrikeIron(array('username' => 'your-username',
  2.                                                 'password' => 'your-password'));
  3.
  4. // Get a client for the Zip Code Information service
  5. $verifier = $strikeIron->getService(array('class' => 'USAddressVerification'));
  6.
  7. // Address to verify. Not all fields are required but
  8. // supply as many as possible for the best results.
  9. $address = array('firm'           => 'Zend Technologies',
  10.                  'addressLine1'   => '19200 Stevens Creek Blvd',
  11.                  'addressLine2'   => '',
  12.                  'city_state_zip' => 'Cupertino CA 95014');
  13.
  14. // Verify the address
  15. $result = $verifier->verifyAddressUSA($address);
  16.
  17. // Display the results
  18. if ($result->addressErrorNumber != 0) {
  19.     echo $result->addressErrorNumber;
  20.     echo $result->addressErrorMessage;
  21. } else {
  22.     // show all properties
  23.     print_r($result);
  24.
  25.     // or just the firm name
  26.     echo $result->firm;
  27.
  28.     // valid address?
  29.     $valid = ($result->valid == 'VALID');
  30. }

Sales & Use Tax Basic

Zend_Service_StrikeIron_SalesUseTaxBasic provides a client for StrikeIron's Sales & Use Tax Basic service. For more information on this service, visit these StrikeIron resources:

  • » Sales & Use Tax Basic Service Page

  • » Sales & Use Tax Basic Service WSDL

The service contains two methods, getTaxRateUSA() and getTaxRateCanada(), that will retrieve sales and use tax data for the United States and Canada, respectively.

  1. $strikeIron = new Zend_Service_StrikeIron(array('username' => 'your-username',
  2.                                                 'password' => 'your-password'));
  3.
  4. // Get a client for the Sales & Use Tax Basic service
  5. $taxBasic = $strikeIron->getService(array('class' => 'SalesUseTaxBasic'));
  6.
  7. // Query tax rate for Ontario, Canada
  8. $rateInfo = $taxBasic->getTaxRateCanada(array('province' => 'foo'));
  9. print_r($rateInfo);               // show all properties
  10. echo $rateInfo->GST;              // or just the GST (Goods & Services Tax)
  11.
  12. // Query tax rate for Cupertino, CA USA
  13. $rateInfo = $taxBasic->getTaxRateUS(array('zip_code' => 95014));
  14. print_r($rateInfo);               // show all properties
  15. echo $rateInfo->state_sales_tax;  // or just the state sales tax

Zend_Service_StrikeIron
Zend_Service
Zend Framework手册 中文版
Zend_Service_StrikeIron: Advanced Uses
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Service
  • 简介
  • Zend_Service_Akismet
  • Zend_Service_Amazon
  • Zend_Service_Amazon_Ec2
  • Zend_Service_Amazon_Ec2: Instances
  • Zend_Service_Amazon_Ec2: Windows Instances
  • Zend_Service_Amazon_Ec2: Reserved Instances
  • Zend_Service_Amazon_Ec2: CloudWatch Monitoring
  • Zend_Service_Amazon_Ec2: Amazon Machine Images (AMI)
  • Zend_Service_Amazon_Ec2: Elastic Block Stroage (EBS)
  • Zend_Service_Amazon_Ec2: Elastic IP Addresses
  • Zend_Service_Amazon_Ec2: Keypairs
  • Zend_Service_Amazon_Ec2: Regions and Availability Zones
  • Zend_Service_Amazon_Ec2: Security Groups
  • Zend_Service_Amazon_S3
  • Zend_Service_Amazon_Sqs
  • Zend_Service_Audioscrobbler
  • Zend_Service_Delicious
  • Zend_Service_DeveloperGarden
  • Zend_Service_Flickr
  • Zend_Service_LiveDocx
  • Zend_Service_Nirvanix
  • Zend_Service_ReCaptcha
  • Zend_Service_Simpy
  • Introduction
  • Zend_Service_StrikeIron
  • Zend_Service_StrikeIron: Bundled Services
  • Zend_Service_StrikeIron: Advanced Uses
  • Zend_Service_Technorati
  • Zend_Service_Twitter
  • Zend_Service_WindowsAzure
  • Zend_Service_Yahoo


Zend_Service_Technorati - Zend Framework Manual

Zend_Service_StrikeIron: Advanced Uses
Zend_Service
Zend Framework手册 中文版
Zend_Service_Twitter

Zend_Service_Technorati

Introduction

Zend_Service_Technorati provides an easy, intuitive and object-oriented interface for using the Technorati API. It provides access to all available » Technorati API queries and returns the original XML response as a friendly PHP object.

» Technorati is one of the most popular blog search engines. The API interface enables developers to retrieve information about a specific blog, search blogs matching a single tag or phrase and get information about a specific author (blogger). For a full list of available queries please see the » Technorati API documentation or the Available Technorati queries section of this document.

Getting Started

Technorati requires a valid API key for usage. To get your own API Key you first need to » create a new Technorati account, then visit the » API Key section.

Note: API Key limits
 You can make up to 500 Technorati API calls per day, at no charge. Other usage limitations may apply, depending on the current Technorati API license.

Once you have a valid API key, you're ready to start using Zend_Service_Technorati.

Making Your First Query

In order to run a query, first you need a Zend_Service_Technorati instance with a valid API key. Then choose one of the available query methods, and call it providing required arguments.

Example #1 Sending your first query

  1. // create a new Zend_Service_Technorati
  2. // with a valid API_KEY
  3. $technorati = new Zend_Service_Technorati('VALID_API_KEY');
  4.
  5. // search Technorati for PHP keyword
  6. $resultSet = $technorati->search('PHP');

Each query method accepts an array of optional parameters that can be used to refine your query.

Example #2 Refining your query

  1. // create a new Zend_Service_Technorati
  2. // with a valid API_KEY
  3. $technorati = new Zend_Service_Technorati('VALID_API_KEY');
  4.
  5. // filter your query including only results
  6. // with some authority (Results from blogs with a handful of links)
  7. $options = array('authority' => 'a4');
  8.
  9. // search Technorati for PHP keyword
  10. $resultSet = $technorati->search('PHP', $options);

A Zend_Service_Technorati instance is not a single-use object. That is, you don't need to create a new instance for each query call; simply use your current Zend_Service_Technorati object as long as you need it.

Example #3 Sending multiple queries with the same Zend_Service_Technorati instance

  1. // create a new Zend_Service_Technorati
  2. // with a valid API_KEY
  3. $technorati = new Zend_Service_Technorati('VALID_API_KEY');
  4.
  5. // search Technorati for PHP keyword
  6. $search = $technorati->search('PHP');
  7.
  8. // get top tags indexed by Technorati
  9. $topTags = $technorati->topTags();

Consuming Results

You can get one of two types of result object in response to a query.

The first group is represented by Zend_Service_Technorati_*ResultSet objects. A result set object is basically a collection of result objects. It extends the basic Zend_Service_Technorati_ResultSet class and implements the SeekableIterator PHP interface. The best way to consume a result set object is to loop over it with the PHP foreach statement.

Example #4 Consuming a result set object

  1. // create a new Zend_Service_Technorati
  2. // with a valid API_KEY
  3. $technorati = new Zend_Service_Technorati('VALID_API_KEY');
  4.
  5. // search Technorati for PHP keyword
  6. // $resultSet is an instance of Zend_Service_Technorati_SearchResultSet
  7. $resultSet = $technorati->search('PHP');
  8.
  9. // loop over all result objects
  10. foreach ($resultSet as $result) {
  11.     // $result is an instance of Zend_Service_Technorati_SearchResult
  12. }

Because Zend_Service_Technorati_ResultSet implements the SeekableIterator interface, you can seek a specific result object using its position in the result collection.

Example #5 Seeking a specific result set object

  1. // create a new Zend_Service_Technorati
  2. // with a valid API_KEY
  3. $technorati = new Zend_Service_Technorati('VALID_API_KEY');
  4.
  5. // search Technorati for PHP keyword
  6. // $resultSet is an instance of Zend_Service_Technorati_SearchResultSet
  7. $resultSet = $technorati->search('PHP');
  8.
  9. // $result is an instance of Zend_Service_Technorati_SearchResult
  10. $resultSet->seek(1);
  11. $result = $resultSet->current();

Note: SeekableIterator works as an array and counts positions starting from index 0. Fetching position number 1 means getting the second result in the collection.

The second group is represented by special standalone result objects. Zend_Service_Technorati_GetInfoResult, Zend_Service_Technorati_BlogInfoResult and Zend_Service_Technorati_KeyInfoResult act as wrappers for additional objects, such as Zend_Service_Technorati_Author and Zend_Service_Technorati_Weblog.

Example #6 Consuming a standalone result object

  1. // create a new Zend_Service_Technorati
  2. // with a valid API_KEY
  3. $technorati = new Zend_Service_Technorati('VALID_API_KEY');
  4.
  5. // get info about weppos author
  6. $result = $technorati->getInfo('weppos');
  7.
  8. $author = $result->getAuthor();
  9. echo '<h2>Blogs authored by ' . $author->getFirstName() . " " .
  10.           $author->getLastName() . '</h2>';
  11. echo '<ol>';
  12. foreach ($result->getWeblogs() as $weblog) {
  13.     echo '<li>' . $weblog->getName() . '</li>';
  14. }
  15. echo "</ol>";

Please read the Zend_Service_Technorati Classes section for further details about response classes.

Handling Errors

Each Zend_Service_Technorati query method throws a Zend_Service_Technorati_Exception exception on failure with a meaningful error message.

There are several reasons that may cause a Zend_Service_Technorati query to fail. Zend_Service_Technorati validates all parameters for any query request. If a parameter is invalid or it contains an invalid value, a new Zend_Service_Technorati_Exception exception is thrown. Additionally, the Technorati API interface could be temporally unavailable, or it could return a response that is not well formed.

You should always wrap a Technorati query with a try...catch block.

Example #7 Handling a Query Exception

  1. $technorati = new Zend_Service_Technorati('VALID_API_KEY');
  2. try {
  3.     $resultSet = $technorati->search('PHP');
  4. } catch(Zend_Service_Technorati_Exception $e) {
  5.     echo "An error occurred: " $e->getMessage();
  6. }

Checking Your API Key Daily Usage

From time to time you probably will want to check your API key daily usage. By default Technorati limits your API usage to 500 calls per day, and an exception is returned by Zend_Service_Technorati if you try to use it beyond this limit. You can get information about your API key usage using the Zend_Service_Technorati::keyInfo() method.

Zend_Service_Technorati::keyInfo() returns a Zend_Service_Technorati_KeyInfoResult object. For full details please see the » API reference guide.

Example #8 Getting API key daily usage information

  1. $technorati = new Zend_Service_Technorati('VALID_API_KEY');
  2. $key = $technorati->keyInfo();
  3.
  4. echo "API Key: " . $key->getApiKey() . "<br />";
  5. echo "Daily Usage: " . $key->getApiQueries() . "/" .
  6.      $key->getMaxQueries() . "<br />";

Available Technorati Queries

Zend_Service_Technorati provides support for the following queries:

  • Cosmos

  • Search

  • Tag

  • DailyCounts

  • TopTags

  • BlogInfo

  • BlogPostTags

  • GetInfo

Technorati Cosmos

» Cosmos query lets you see what blogs are linking to a given URL. It returns a Zend_Service_Technorati_CosmosResultSet object. For full details please see Zend_Service_Technorati::cosmos() in the » API reference guide.

Example #9 Cosmos Query

  1. $technorati = new Zend_Service_Technorati('VALID_API_KEY');
  2. $resultSet = $technorati->cosmos('http://devzone.zend.com/');
  3.
  4. echo "<p>Reading " . $resultSet->totalResults() .
  5.      " of " . $resultSet->totalResultsAvailable() .
  6.      " available results</p>";
  7. echo "<ol>";
  8. foreach ($resultSet as $result) {
  9.     echo "<li>" . $result->getWeblog()->getName() . "</li>";
  10. }
  11. echo "</ol>";

Technorati Search

The » Search query lets you see what blogs contain a given search string. It returns a Zend_Service_Technorati_SearchResultSet object. For full details please see Zend_Service_Technorati::search() in the » API reference guide.

Example #10 Search Query

  1. $technorati = new Zend_Service_Technorati('VALID_API_KEY');
  2. $resultSet = $technorati->search('zend framework');
  3.
  4. echo "<p>Reading " . $resultSet->totalResults() .
  5.      " of " . $resultSet->totalResultsAvailable() .
  6.      " available results</p>";
  7. echo "<ol>";
  8. foreach ($resultSet as $result) {
  9.     echo "<li>" . $result->getWeblog()->getName() . "</li>";
  10. }
  11. echo "</ol>";

Technorati Tag

The » Tag query lets you see what posts are associated with a given tag. It returns a Zend_Service_Technorati_TagResultSet object. For full details please see Zend_Service_Technorati::tag() in the » API reference guide.

Example #11 Tag Query

  1. $technorati = new Zend_Service_Technorati('VALID_API_KEY');
  2. $resultSet = $technorati->tag('php');
  3.
  4. echo "<p>Reading " . $resultSet->totalResults() .
  5.      " of " . $resultSet->totalResultsAvailable() .
  6.      " available results</p>";
  7. echo "<ol>";
  8. foreach ($resultSet as $result) {
  9.     echo "<li>" . $result->getWeblog()->getName() . "</li>";
  10. }
  11. echo "</ol>";

Technorati DailyCounts

The » DailyCounts query provides daily counts of posts containing the queried keyword. It returns a Zend_Service_Technorati_DailyCountsResultSet object. For full details please see Zend_Service_Technorati::dailyCounts() in the » API reference guide.

Example #12 DailyCounts Query

  1. $technorati = new Zend_Service_Technorati('VALID_API_KEY');
  2. $resultSet = $technorati->dailyCounts('php');
  3.
  4. foreach ($resultSet as $result) {
  5.     echo "<li>" . $result->getDate() .
  6.          "(" . $result->getCount() . ")</li>";
  7. }
  8. echo "</ol>";

Technorati TopTags

The » TopTags query provides information on top tags indexed by Technorati. It returns a Zend_Service_Technorati_TagsResultSet object. For full details please see Zend_Service_Technorati::topTags() in the » API reference guide.

Example #13 TopTags Query

  1. $technorati = new Zend_Service_Technorati('VALID_API_KEY');
  2. $resultSet = $technorati->topTags();
  3.
  4. echo "<p>Reading " . $resultSet->totalResults() .
  5.      " of " . $resultSet->totalResultsAvailable() .
  6.      " available results</p>";
  7. echo "<ol>";
  8. foreach ($resultSet as $result) {
  9.     echo "<li>" . $result->getTag() . "</li>";
  10. }
  11. echo "</ol>";

Technorati BlogInfo

The » BlogInfo query provides information on what blog, if any, is associated with a given URL. It returns a Zend_Service_Technorati_BlogInfoResult object. For full details please see Zend_Service_Technorati::blogInfo() in the » API reference guide.

Example #14 BlogInfo Query

  1. $technorati = new Zend_Service_Technorati('VALID_API_KEY');
  2. $result = $technorati->blogInfo('http://devzone.zend.com/');
  3.
  4. echo '<h2><a href="' . (string) $result->getWeblog()->getUrl() . '">' .
  5.      $result->getWeblog()->getName() . '</a></h2>';

Technorati BlogPostTags

The » BlogPostTags query provides information on the top tags used by a specific blog. It returns a Zend_Service_Technorati_TagsResultSet object. For full details please see Zend_Service_Technorati::blogPostTags() in the » API reference guide.

Example #15 BlogPostTags Query

  1. $technorati = new Zend_Service_Technorati('VALID_API_KEY');
  2. $resultSet = $technorati->blogPostTags('http://devzone.zend.com/');
  3.
  4. echo "<p>Reading " . $resultSet->totalResults() .
  5.      " of " . $resultSet->totalResultsAvailable() .
  6.      " available results</p>";
  7. echo "<ol>";
  8. foreach ($resultSet as $result) {
  9.     echo "<li>" . $result->getTag() . "</li>";
  10. }
  11. echo "</ol>";

Technorati GetInfo

The » GetInfo query tells you things that Technorati knows about a member. It returns a Zend_Service_Technorati_GetInfoResult object. For full details please see Zend_Service_Technorati::getInfo() in the » API reference guide.

Example #16 GetInfo Query

  1. $technorati = new Zend_Service_Technorati('VALID_API_KEY');
  2. $result = $technorati->getInfo('weppos');
  3.
  4. $author = $result->getAuthor();
  5. echo "<h2>Blogs authored by " . $author->getFirstName() . " " .
  6.      $author->getLastName() . "</h2>";
  7. echo "<ol>";
  8. foreach ($result->getWeblogs() as $weblog) {
  9.     echo "<li>" . $weblog->getName() . "</li>";
  10. }
  11. echo "</ol>";

Technorati KeyInfo

The KeyInfo query provides information on daily usage of an API key. It returns a Zend_Service_Technorati_KeyInfoResult object. For full details please see Zend_Service_Technorati::keyInfo() in the » API reference guide.

Zend_Service_Technorati Classes

The following classes are returned by the various Technorati queries. Each Zend_Service_Technorati_*ResultSet class holds a type-specific result set which can be easily iterated, with each result being contained in a type result object. All result set classes extend Zend_Service_Technorati_ResultSet class and implement the SeekableIterator interface, allowing for easy iteration and seeking to a specific result.

  • Zend_Service_Technorati_ResultSet

  • Zend_Service_Technorati_CosmosResultSet

  • Zend_Service_Technorati_SearchResultSet

  • Zend_Service_Technorati_TagResultSet

  • Zend_Service_Technorati_DailyCountsResultSet

  • Zend_Service_Technorati_TagsResultSet

  • Zend_Service_Technorati_Result

  • Zend_Service_Technorati_CosmosResult

  • Zend_Service_Technorati_SearchResult

  • Zend_Service_Technorati_TagResult

  • Zend_Service_Technorati_DailyCountsResult

  • Zend_Service_Technorati_TagsResult

  • Zend_Service_Technorati_GetInfoResult

  • Zend_Service_Technorati_BlogInfoResult

  • Zend_Service_Technorati_KeyInfoResult

Note: Zend_Service_Technorati_GetInfoResult, Zend_Service_Technorati_BlogInfoResult and Zend_Service_Technorati_KeyInfoResult represent exceptions to the above because they don't belong to a result set and they don't implement any interface. They represent a single response object and they act as a wrapper for additional Zend_Service_Technorati objects, such as Zend_Service_Technorati_Author and Zend_Service_Technorati_Weblog.

The Zend_Service_Technorati library includes additional convenient classes representing specific response objects. Zend_Service_Technorati_Author represents a single Technorati account, also known as a blog author or blogger. Zend_Service_Technorati_Weblog represents a single weblog object, along with all specific weblog properties such as feed URLs or blog name. For full details please see Zend_Service_Technorati in the » API reference guide.

Zend_Service_Technorati_ResultSet

Zend_Service_Technorati_ResultSet is the most essential result set. The scope of this class is to be extended by a query-specific child result set class, and it should never be used to initialize a standalone object. Each of the specific result sets represents a collection of query-specific Zend_Service_Technorati_Result objects.

Zend_Service_Technorati_ResultSet implements the PHP SeekableIterator interface, and you can iterate all result objects via the PHP foreach statement.

Example #17 Iterating result objects from a resultset collection

  1. // run a simple query
  2. $technorati = new Zend_Service_Technorati('VALID_API_KEY');
  3. $resultSet = $technorati->search('php');
  4.
  5. // $resultSet is now an instance of
  6. // Zend_Service_Technorati_SearchResultSet
  7. // it extends Zend_Service_Technorati_ResultSet
  8. foreach ($resultSet as $result) {
  9.     // do something with your
  10.     // Zend_Service_Technorati_SearchResult object
  11. }

Zend_Service_Technorati_CosmosResultSet

Zend_Service_Technorati_CosmosResultSet represents a Technorati Cosmos query result set.

Note: Zend_Service_Technorati_CosmosResultSet extends Zend_Service_Technorati_ResultSet.

Zend_Service_Technorati_SearchResultSet

Zend_Service_Technorati_SearchResultSet represents a Technorati Search query result set.

Note: Zend_Service_Technorati_SearchResultSet extends Zend_Service_Technorati_ResultSet.

Zend_Service_Technorati_TagResultSet

Zend_Service_Technorati_TagResultSet represents a Technorati Tag query result set.

Note: Zend_Service_Technorati_TagResultSet extends Zend_Service_Technorati_ResultSet.

Zend_Service_Technorati_DailyCountsResultSet

Zend_Service_Technorati_DailyCountsResultSet represents a Technorati DailyCounts query result set.

Note: Zend_Service_Technorati_DailyCountsResultSet extends Zend_Service_Technorati_ResultSet.

Zend_Service_Technorati_TagsResultSet

Zend_Service_Technorati_TagsResultSet represents a Technorati TopTags or BlogPostTags queries result set.

Note: Zend_Service_Technorati_TagsResultSet extends Zend_Service_Technorati_ResultSet.

Zend_Service_Technorati_Result

Zend_Service_Technorati_Result is the most essential result object. The scope of this class is to be extended by a query specific child result class, and it should never be used to initialize a standalone object.

Zend_Service_Technorati_CosmosResult

Zend_Service_Technorati_CosmosResult represents a single Technorati Cosmos query result object. It is never returned as a standalone object, but it always belongs to a valid Zend_Service_Technorati_CosmosResultSet object.

Note: Zend_Service_Technorati_CosmosResult extends Zend_Service_Technorati_Result.

Zend_Service_Technorati_SearchResult

Zend_Service_Technorati_SearchResult represents a single Technorati Search query result object. It is never returned as a standalone object, but it always belongs to a valid Zend_Service_Technorati_SearchResultSet object.

Note: Zend_Service_Technorati_SearchResult extends Zend_Service_Technorati_Result.

Zend_Service_Technorati_TagResult

Zend_Service_Technorati_TagResult represents a single Technorati Tag query result object. It is never returned as a standalone object, but it always belongs to a valid Zend_Service_Technorati_TagResultSet object.

Note: Zend_Service_Technorati_TagResult extends Zend_Service_Technorati_Result.

Zend_Service_Technorati_DailyCountsResult

Zend_Service_Technorati_DailyCountsResult represents a single Technorati DailyCounts query result object. It is never returned as a standalone object, but it always belongs to a valid Zend_Service_Technorati_DailyCountsResultSet object.

Note: Zend_Service_Technorati_DailyCountsResult extends Zend_Service_Technorati_Result.

Zend_Service_Technorati_TagsResult

Zend_Service_Technorati_TagsResult represents a single Technorati TopTags or BlogPostTags query result object. It is never returned as a standalone object, but it always belongs to a valid Zend_Service_Technorati_TagsResultSet object.

Note: Zend_Service_Technorati_TagsResult extends Zend_Service_Technorati_Result.

Zend_Service_Technorati_GetInfoResult

Zend_Service_Technorati_GetInfoResult represents a single Technorati GetInfo query result object.

Zend_Service_Technorati_BlogInfoResult

Zend_Service_Technorati_BlogInfoResult represents a single Technorati BlogInfo query result object.

Zend_Service_Technorati_KeyInfoResult

Zend_Service_Technorati_KeyInfoResult represents a single Technorati KeyInfo query result object. It provides information about your Technorati API Key daily usage.

Zend_Service_StrikeIron: Advanced Uses
Zend_Service
Zend Framework手册 中文版
Zend_Service_Twitter
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Service
  • 简介
  • Zend_Service_Akismet
  • Zend_Service_Amazon
  • Zend_Service_Amazon_Ec2
  • Zend_Service_Amazon_Ec2: Instances
  • Zend_Service_Amazon_Ec2: Windows Instances
  • Zend_Service_Amazon_Ec2: Reserved Instances
  • Zend_Service_Amazon_Ec2: CloudWatch Monitoring
  • Zend_Service_Amazon_Ec2: Amazon Machine Images (AMI)
  • Zend_Service_Amazon_Ec2: Elastic Block Stroage (EBS)
  • Zend_Service_Amazon_Ec2: Elastic IP Addresses
  • Zend_Service_Amazon_Ec2: Keypairs
  • Zend_Service_Amazon_Ec2: Regions and Availability Zones
  • Zend_Service_Amazon_Ec2: Security Groups
  • Zend_Service_Amazon_S3
  • Zend_Service_Amazon_Sqs
  • Zend_Service_Audioscrobbler
  • Zend_Service_Delicious
  • Zend_Service_DeveloperGarden
  • Zend_Service_Flickr
  • Zend_Service_LiveDocx
  • Zend_Service_Nirvanix
  • Zend_Service_ReCaptcha
  • Zend_Service_Simpy
  • Introduction
  • Zend_Service_StrikeIron
  • Zend_Service_StrikeIron: Bundled Services
  • Zend_Service_StrikeIron: Advanced Uses
  • Zend_Service_Technorati
  • Zend_Service_Twitter
  • Zend_Service_WindowsAzure
  • Zend_Service_Yahoo


Zend_Service_Twitter - Zend Framework Manual

Zend_Service_Technorati
Zend_Service
Zend Framework手册 中文版
Zend_Service_WindowsAzure

Zend_Service_Twitter

Introduction

Zend_Service_Twitter provides a client for the » Twitter REST API. Zend_Service_Twitter allows you to query the public timeline. If you provide a username and password for Twitter, it will allow you to get and update your status, reply to friends, direct message friends, mark tweets as favorite, and much more.

Zend_Service_Twitter is implementing a REST service, and all methods return an instance of Zend_Rest_Client_Result.

Zend_Service_Twitter is broken up into subsections so you can easily identify which type of call is being requested.

  • account makes sure that your account credentials are valid, checks your API rate limit, and ends the current session for the authenticated user.

  • status retrieves the public and user timelines and shows, updates, destroys, and retrieves replies for the authenticated user.

  • user retrieves friends and followers for the authenticated user and returns extended information about a passed user.

  • directMessage retrieves the authenticated user's received direct messages, deletes direct messages, and sends new direct messages.

  • friendship creates and removes friendships for the authenticated user.

  • favorite lists, creates, and removes favorite tweets.

  • block blocks and unblocks users from following you.

Authentication

With the exception of fetching the public timeline, Zend_Service_Twitter requires authentication to work. Twitter currently uses » HTTP Basic Authentication. You can pass in your username or registered email along with your password for Twitter to login.

Example #1 Creating the Twitter Class

The following code sample is how you create the Twitter service, pass in your username and password, and verify that they are correct.

  1. $twitter = new Zend_Service_Twitter('myusername', 'mysecretpassword');
  2.
  3. // verify your credentials with Twitter
  4. $response = $twitter->account->verifyCredentials();

You can also pass in an array that contains the username and password as the first argument.

  1. $userInfo   = array('username' => 'foo', 'password' => 'bar');
  2. $twitter    = new Zend_Service_Twitter($userInfo);
  3.
  4. // verify your credentials with Twitter
  5. $response = $twitter->account->verifyCredentials();

Account Methods

  • verifyCredentials() tests if supplied user credentials are valid with minimal overhead.

    Example #2 Verifying credentials

    1. $twitter    = new Zend_Service_Twitter('myusername', 'mysecretpassword');
    2. $response   = $twitter->account->verifyCredentials();

  • endSession() signs users out of client-facing applications.

    Example #3 Sessions ending

    1. $twitter    = new Zend_Service_Twitter('myusername', 'mysecretpassword');
    2. $response   = $twitter->account->endSession();

  • rateLimitStatus() returns the remaining number of API requests available to the authenticating user before the API limit is reached for the current hour.

    Example #4 Rating limit status

    1. $twitter    = new Zend_Service_Twitter('myusername', 'mysecretpassword');
    2. $response   = $twitter->account->rateLimitStatus();

Status Methods

  • publicTimeline() returns the 20 most recent statuses from non-protected users with a custom user icon. The public timeline is cached by Twitter for 60 seconds.

    Example #5 Retrieving public timeline

    1. $twitter    = new Zend_Service_Twitter('myusername', 'mysecretpassword');
    2. $response   = $twitter->status->publicTimeline();

  • friendsTimeline() returns the 20 most recent statuses posted by the authenticating user and that user's friends.

    Example #6 Retrieving friends timeline

    1. $twitter    = new Zend_Service_Twitter('myusername', 'mysecretpassword');
    2. $response   = $twitter->status->friendsTimeline();

    The friendsTimeline() method accepts an array of optional parameters to modify the query.

    • since narrows the returned results to just those statuses created after the specified date/time (up to 24 hours old).

    • page specifies which page you want to return.

  • userTimeline() returns the 20 most recent statuses posted from the authenticating user.

    Example #7 Retrieving user timeline

    1. $twitter    = new Zend_Service_Twitter('myusername', 'mysecretpassword');
    2. $response   = $twitter->status->userTimeline();

    The userTimeline() method accepts an array of optional parameters to modify the query.

    • id specifies the ID or screen name of the user for whom to return the friends_timeline.

    • since narrows the returned results to just those statuses created after the specified date/time (up to 24 hours old).

    • page specifies which page you want to return.

    • count specifies the number of statuses to retrieve. May not be greater than 200.

  • show() returns a single status, specified by the id parameter below. The status' author will be returned inline.

    Example #8 Showing user status

    1. $twitter    = new Zend_Service_Twitter('myusername', 'mysecretpassword');
    2. $response   = $twitter->status->show(1234);

  • update() updates the authenticating user's status. This method requires that you pass in the status update that you want to post to Twitter.

    Example #9 Updating user status

    1. $twitter    = new Zend_Service_Twitter('myusername', 'mysecretpassword');
    2. $response   = $twitter->status->update('My Great Tweet');

    The update() method accepts a second additional parameter.

    • in_reply_to_status_id specifies the ID of an existing status that the status to be posted is in reply to.

  • replies() returns the 20 most recent @replies (status updates prefixed with @username) for the authenticating user.

    Example #10 Showing user replies

    1. $twitter    = new Zend_Service_Twitter('myusername', 'mysecretpassword');
    2. $response   = $twitter->status->replies();

    The replies() method accepts an array of optional parameters to modify the query.

    • since narrows the returned results to just those statuses created after the specified date/time (up to 24 hours old).

    • page specifies which page you want to return.

    • since_id returns only statuses with an ID greater than (that is, more recent than) the specified ID.

  • destroy() destroys the status specified by the required id parameter.

    Example #11 Deleting user status

    1. $twitter    = new Zend_Service_Twitter('myusername', 'mysecretpassword');
    2. $response   = $twitter->status->destroy(12345);

User Methods

  • friends()r eturns up to 100 of the authenticating user's friends who have most recently updated, each with current status inline.

    Example #12 Retrieving user friends

    1. $twitter    = new Zend_Service_Twitter('myusername', 'mysecretpassword');
    2. $response   = $twitter->user->friends();

    The friends() method accepts an array of optional parameters to modify the query.

    • id specifies the ID or screen name of the user for whom to return a list of friends.

    • since narrows the returned results to just those statuses created after the specified date/time (up to 24 hours old).

    • page specifies which page you want to return.

  • followers() returns the authenticating user's followers, each with current status inline.

    Example #13 Retrieving user followers

    1. $twitter    = new Zend_Service_Twitter('myusername', 'mysecretpassword');
    2. $response   = $twitter->user->followers();

    The followers() method accepts an array of optional parameters to modify the query.

    • id specifies the ID or screen name of the user for whom to return a list of followers.

    • page specifies which page you want to return.

  • show() returns extended information of a given user, specified by ID or screen name as per the required id parameter below.

    Example #14 Showing user informations

    1. $twitter    = new Zend_Service_Twitter('myusername', 'mysecretpassword');
    2. $response   = $twitter->user->show('myfriend');

Direct Message Methods

  • messages() returns a list of the 20 most recent direct messages sent to the authenticating user.

    Example #15 Retrieving recent direct messages received

    1. $twitter    = new Zend_Service_Twitter('myusername', 'mysecretpassword');
    2. $response   = $twitter->directMessage->messages();

    The message() method accepts an array of optional parameters to modify the query.

    • since_id returns only direct messages with an ID greater than (that is, more recent than) the specified ID.

    • since narrows the returned results to just those statuses created after the specified date/time (up to 24 hours old).

    • page specifies which page you want to return.

  • sent() returns a list of the 20 most recent direct messages sent by the authenticating user.

    Example #16 Retrieving recent direct messages sent

    1. $twitter    = new Zend_Service_Twitter('myusername', 'mysecretpassword');
    2. $response   = $twitter->directMessage->sent();

    The sent() method accepts an array of optional parameters to modify the query.

    • since_id returns only direct messages with an ID greater than (that is, more recent than) the specified ID.

    • since narrows the returned results to just those statuses created after the specified date/time (up to 24 hours old).

    • page specifies which page you want to return.

  • new() sends a new direct message to the specified user from the authenticating user. Requires both the user and text parameters below.

    Example #17 Sending direct message

    1. $twitter    = new Zend_Service_Twitter('myusername', 'mysecretpassword');
    2. $response   = $twitter->directMessage->new('myfriend', 'mymessage');

  • destroy() destroys the direct message specified in the required id parameter. The authenticating user must be the recipient of the specified direct message.

    Example #18 Deleting direct message

    1. $twitter    = new Zend_Service_Twitter('myusername', 'mysecretpassword');
    2. $response   = $twitter->directMessage->destroy(123548);

Friendship Methods

  • create() befriends the user specified in the id parameter with the authenticating user.

    Example #19 Creating friend

    1. $twitter    = new Zend_Service_Twitter('myusername', 'mysecretpassword');
    2. $response   = $twitter->friendship->create('mynewfriend');

  • destroy() discontinues friendship with the user specified in the id parameter and the authenticating user.

    Example #20 Deleting friend

    1. $twitter    = new Zend_Service_Twitter('myusername', 'mysecretpassword');
    2. $response   = $twitter->friendship->destroy('myoldfriend');

  • exists() tests if a friendship exists between the user specified in the id parameter and the authenticating user.

    Example #21 Checking friend existence

    1. $twitter    = new Zend_Service_Twitter('myusername', 'mysecretpassword');
    2. $response   = $twitter->friendship->exists('myfriend');

Favorite Methods

  • favorites() returns the 20 most recent favorite statuses for the authenticating user or user specified by the id parameter.

    Example #22 Retrieving favorites

    1. $twitter    = new Zend_Service_Twitter('myusername', 'mysecretpassword');
    2. $response   = $twitter->favorite->favorites();

    The favorites() method accepts an array of optional parameters to modify the query.

    • id specifies the ID or screen name of the user for whom to request a list of favorite statuses.

    • page specifies which page you want to return.

  • create() favorites the status specified in the id parameter as the authenticating user.

    Example #23 Creating favorites

    1. $twitter    = new Zend_Service_Twitter('myusername', 'mysecretpassword');
    2. $response   = $twitter->favorite->create(12351);

  • destroy() un-favorites the status specified in the id parameter as the authenticating user.

    Example #24 Deleting favorites

    1. $twitter    = new Zend_Service_Twitter('myusername', 'mysecretpassword');
    2. $response   = $twitter->favorite->destroy(12351);

Block Methods

  • exists() checks if the authenticating user is blocking a target user and can optionally return the blocked user's object if a block does exists.

    Example #25 Checking if block exists

    1. $twitter = new Zend_Service_Twitter('myusername', 'mysecretpassword');
    2.
    3. // returns true or false
    4. $response = $twitter->block->exists('blockeduser');
    5.
    6. // returns the blocked user's info if the user is blocked
    7. $response2 = $twitter->block->exists('blockeduser', true);

    The favorites() method accepts a second optional parameter.

    • returnResult specifies whether or not return the user object instead of just TRUE or FALSE.

  • create() blocks the user specified in the id parameter as the authenticating user and destroys a friendship to the blocked user if one exists. Returns the blocked user in the requested format when successful.

    Example #26 Blocking a user

    1. $twitter    = new Zend_Service_Twitter('myusername', 'mysecretpassword');
    2. $response   = $twitter->block->create('usertoblock);

  • destroy() un-blocks the user specified in the id parameter for the authenticating user. Returns the un-blocked user in the requested format when successful.

    Example #27 Removing a block

    1. $twitter    = new Zend_Service_Twitter('myusername', 'mysecretpassword');
    2. $response   = $twitter->block->destroy('blockeduser');

  • blocking() returns an array of user objects that the authenticating user is blocking.

    Example #28 Who are you blocking

    1. $twitter = new Zend_Service_Twitter('myusername', 'mysecretpassword');
    2.
    3. // return the full user list from the first page
    4. $response = $twitter->block->blocking();
    5.
    6. // return an array of numeric user IDs from the second page
    7. $response2 = $twitter->block->blocking(2, true);

    The favorites() method accepts two optional parameters.

    • page specifies which page ou want to return. A single page contains 20 IDs.

    • returnUserIds specifies whether to return an array of numeric user IDs the authenticating user is blocking instead of an array of user objects.

Zend_Service_Twitter_Search

Introduction

Zend_Service_Twitter_Search provides a client for the » Twitter Search API. The Twitter Search service is use to search Twitter. Currently, it only returns data in Atom or JSON format, but a full REST service is in the future, which will support XML responses.

Twitter Trends

Returns the top ten queries that are currently trending on Twitter. The response includes the time of the request, the name of each trending topic, and the url to the Twitter Search results page for that topic. Currently the search API for trends only supports a JSON return so the function returns an array.

  1. $twitterSearch  = new Zend_Service_Twitter_Search();
  2. $twitterTrends  = $twitterSearch->trends();
  3.
  4. foreach ($twitterTrends as $trend) {
  5.     print $trend['name'] . ' - ' . $trend['url'] . PHP_EOL
  6. }

The return array has two values in it:

  • name is the name of trend.

  • url is the URL to see the tweets for that trend.

Searching Twitter

Using the search method returns tweets that match a specific query. There are a number of » Search Operators that you can use to query with.

The search method can accept six different optional URL parameters passed in as an array:

  • lang restricts the tweets to a given language. lang must be given by an » ISO 639-1 code.

  • rpp is the number of tweets to return per page, up to a maximum of 100.

  • page specifies the page number to return, up to a maximum of roughly 1500 results (based on rpp * page).

  • since_id returns tweets with status IDs greater than the given ID.

  • show_user specifies whether to add ">user<:" to the beginning of the tweet. This is useful for readers that do not display Atom's author field. The default is "FALSE".

  • geocode returns tweets by users located within a given radius of the given latitude/longitude, where the user's location is taken from their Twitter profile. The parameter value is specified by "latitude,longitude,radius", where radius units must be specified as either "mi" (miles) or "km" (kilometers).

Example #29 JSON Search Example

The following code sample will return an array with the search results.

  1. $twitterSearch  = new Zend_Service_Twitter_Search('json');
  2. $searchResults  = $twitterSearch->search('zend', array('lang' => 'en'));

Example #30 ATOM Search Example

The following code sample will return a Zend_Feed_Atom object.

  1. $twitterSearch  = new Zend_Service_Twitter_Search('atom');
  2. $searchResults  = $twitterSearch->search('zend', array('lang' => 'en'));

Zend-specific Accessor Methods

While the Twitter Search API only specifies two methods, Zend_Service_Twitter_Search has additional methods that may be used for retrieving and modifying internal properties.

  • getResponseType() and setResponseType() allow you to retrieve and modify the response type of the search between JSON and Atom.

Zend_Service_Technorati
Zend_Service
Zend Framework手册 中文版
Zend_Service_WindowsAzure
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Service
  • 简介
  • Zend_Service_Akismet
  • Zend_Service_Amazon
  • Zend_Service_Amazon_Ec2
  • Zend_Service_Amazon_Ec2: Instances
  • Zend_Service_Amazon_Ec2: Windows Instances
  • Zend_Service_Amazon_Ec2: Reserved Instances
  • Zend_Service_Amazon_Ec2: CloudWatch Monitoring
  • Zend_Service_Amazon_Ec2: Amazon Machine Images (AMI)
  • Zend_Service_Amazon_Ec2: Elastic Block Stroage (EBS)
  • Zend_Service_Amazon_Ec2: Elastic IP Addresses
  • Zend_Service_Amazon_Ec2: Keypairs
  • Zend_Service_Amazon_Ec2: Regions and Availability Zones
  • Zend_Service_Amazon_Ec2: Security Groups
  • Zend_Service_Amazon_S3
  • Zend_Service_Amazon_Sqs
  • Zend_Service_Audioscrobbler
  • Zend_Service_Delicious
  • Zend_Service_DeveloperGarden
  • Zend_Service_Flickr
  • Zend_Service_LiveDocx
  • Zend_Service_Nirvanix
  • Zend_Service_ReCaptcha
  • Zend_Service_Simpy
  • Introduction
  • Zend_Service_StrikeIron
  • Zend_Service_StrikeIron: Bundled Services
  • Zend_Service_StrikeIron: Advanced Uses
  • Zend_Service_Technorati
  • Zend_Service_Twitter
  • Zend_Service_WindowsAzure
  • Zend_Service_Yahoo


Zend_Service_WindowsAzure - Zend Framework Manual

Zend_Service_Twitter
Zend_Service
Zend Framework手册 中文版
Zend_Service_Yahoo

Zend_Service_WindowsAzure

Introduction

Windows Azure is the name for Microsoft’s Software + Services platform, an operating system in the cloud providing services for hosting, management, scalable storage with support for simple blobs, tables, and queues, as well as a management infrastructure for provisioning and geo-distribution of cloud-based services, and a development platform for the Azure Services layer.

Installing the Windows Azure SDK

There are two development scenario's when working with Windows Azure.

  • You can develop your application using Zend_Service_WindowsAzure and the Windows Azure SDK, which provides a local developent environment of the services provided by Windows Azure's cloud infrastructure.

  • You can develop your application using Zend_Service_WindowsAzure, working directly with the Windows Azure cloud infrastructure.

The first case requires you to install the » Windows Azure SDK on your development machine. It is currently only available for Windows environments; progress is being made on a Java-based version of the SDK which can run on any platform.

The latter case requires you to have an account at » Azure.com.

API Documentation

The Zend_Service_WindowsAzure class provides the PHP wrapper to the Windows Azure REST interface. Please consult the » REST documentation for detailed description of the service. You will need to be familiar with basic concepts in order to use this service.

Features

Zend_Service_WindowsAzure provides the following functionality:

  • PHP classes for Windows Azure Blobs, Tables and Queues (for CRUD operations)

  • Helper Classes for HTTP transport, AuthN/AuthZ, REST and Error Management

  • Manageability, Instrumentation and Logging support

Architecture

Zend_Service_WindowsAzure provides access to Windows Azure's storage, computation and management interfaces by abstracting the REST/XML interface Windows Azure provides into a simple PHP API.

An application built using Zend_Service_WindowsAzure can access Windows Azure's features, no matter if it is hosted on the Windows Azure platform or on an in-premise web server.

Zend_Service_Twitter
Zend_Service
Zend Framework手册 中文版
Zend_Service_Yahoo
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Service
  • 简介
  • Zend_Service_Akismet
  • Zend_Service_Amazon
  • Zend_Service_Amazon_Ec2
  • Zend_Service_Amazon_Ec2: Instances
  • Zend_Service_Amazon_Ec2: Windows Instances
  • Zend_Service_Amazon_Ec2: Reserved Instances
  • Zend_Service_Amazon_Ec2: CloudWatch Monitoring
  • Zend_Service_Amazon_Ec2: Amazon Machine Images (AMI)
  • Zend_Service_Amazon_Ec2: Elastic Block Stroage (EBS)
  • Zend_Service_Amazon_Ec2: Elastic IP Addresses
  • Zend_Service_Amazon_Ec2: Keypairs
  • Zend_Service_Amazon_Ec2: Regions and Availability Zones
  • Zend_Service_Amazon_Ec2: Security Groups
  • Zend_Service_Amazon_S3
  • Zend_Service_Amazon_Sqs
  • Zend_Service_Audioscrobbler
  • Zend_Service_Delicious
  • Zend_Service_DeveloperGarden
  • Zend_Service_Flickr
  • Zend_Service_LiveDocx
  • Zend_Service_Nirvanix
  • Zend_Service_ReCaptcha
  • Zend_Service_Simpy
  • Introduction
  • Zend_Service_StrikeIron
  • Zend_Service_StrikeIron: Bundled Services
  • Zend_Service_StrikeIron: Advanced Uses
  • Zend_Service_Technorati
  • Zend_Service_Twitter
  • Zend_Service_WindowsAzure
  • Zend_Service_Yahoo


Zend_Service_Yahoo - Zend Framework Manual

Zend_Service_WindowsAzure
Zend_Service
Zend Framework手册 中文版
Zend_Session

Zend_Service_Yahoo

简介

Zend_Service_Yahoo 是一个实现多个Yahoo! REST 接口的API. Zend_Service_Yahoo 允许你使用Yahoo! 网页搜索, Yahoo! 新闻, Yahoo! 本地(Local), Yahoo! 图片. 为了使用 Yahoo! REST API, 你必须拥有一个 Yahoo! Application ID. 要获得它, 请访问 » Application ID Request Form.

用Yahoo!来搜索网页

Zend_Service_Yahoo 允许你用 webSearch() 方法来进行Yahoo! 网页搜索, 它接受一个查询字符串作为参数 ， 用一个可选的数组传递搜索选项. 更多的细节和搜索选项的信息, 请访问 » Yahoo! Web Search Documentation. webSearch() 方法返回一个 Zend_Service_Yahoo_WebResultSet 对象.

Example #1 用Yahoo!来搜索网页

<?php
require_once 'Zend/Service/Yahoo.php';
$yahoo = new Zend_Service_Yahoo("YAHOO_APPLICATION_ID");
$results = $yahoo->webSearch('PHP');
foreach ($results as $result) {
    echo $result->Title .'<br />';
}
?>

用Yahoo!来查找图片

你可以使用Zend_Service_Yahoo的 imageSearch() 方法来在Yahoo上搜索图片。 。 它接受一个查询字符串作为参数 ，用一个可选的数组传递搜索选项, 就像 webSearch() method. 更多的细节和搜索选项的信息, 请访问 » Yahoo! Image Search Documentation.

Example #2 用Yahoo!来查找图片

<?php
require_once 'Zend/Service/Yahoo.php';
$yahoo = new Zend_Service_Yahoo("YAHOO_APPLICATION_ID");
$results = $yahoo->imageSearch('PHP');
foreach ($results as $result) {
    echo $result->Title .'<br />';
}
?>

Finding Local Businesses and Services with Yahoo!

You can search for local businesses and services with Yahoo! by using the localSearch() method. For full details, please see the » Yahoo! Local Search Documentation.

Example #3 用Yahoo!查找本地商务和服务信息

<?php
require_once 'Zend/Service/Yahoo.php';
$yahoo = new Zend_Service_Yahoo("YAHOO_APPLICATION_ID");
$results = $yahoo->localSearch('Apple Computers', array('zip' => '95014'));
foreach ($results as $result) {
    echo $result->Title .'<br />';
}
?>

搜索Yahoo! 新闻

搜索Yahoo! 新闻非常简单; 使用 newsSearch() 方法, 如下面的例子. 更多的细节和搜索选项的信息, 请访问 » Yahoo! News Search Documentation.

Example #4 搜索Yahoo! 新闻

<?php
require_once 'Zend/Service/Yahoo.php';
$yahoo = new Zend_Service_Yahoo("YAHOO_APPLICATION_ID");
$results = $yahoo->newsSearch('PHP');
foreach ($results as $result) {
    echo $result->Title .'<br />';
}
?>

Zend_Service_Yahoo 类

不同的Yahoo! 搜索类型会返回下面的这些类. 每个搜索类型返回指定类型的结果集, 我们可以很方便的对它们进行遍历, 每个结果被包含在一种类型的结果集对象中. 所有这些对象都实现了 SeekableIterator 接口, 可以很容易的进行遍历和寻找指定结果。

  • Zend_Service_Yahoo_ResultSet

  • Zend_Service_Yahoo_WebResultSet

  • Zend_Service_Yahoo_ImageResultSet

  • Zend_Service_Yahoo_LocalResultSet

  • Zend_Service_Yahoo_NewsResultSet

  • Zend_Service_Yahoo_Result

  • Zend_Service_Yahoo_WebResult

  • Zend_Service_Yahoo_ImageResult

  • Zend_Service_Yahoo_LocalResult

  • Zend_Service_Yahoo_NewsResult

  • Zend_Service_Yahoo_Image

Zend_Service_Yahoo_ResultSet

每类搜索特定的结果集都由这个基类扩展而成

每类搜索特定的结果集都会返回这个搜索特定的 Zend_Service_Yahoo_Result 对象.

Zend_Service_Yahoo_ResultSet::totalResults()

int totalResults ( void )

返回搜索结果的数量

Properties

Zend_Service_Yahoo_ResultSet
名称 | 类型 | 描述
totalResultsAvailable | int | 所有找到的结果的数量
totalResultsReturned | int | 当前结果集中结果的数量
firstResultPosition | int | 当前结果集中的第一条在所有结果中的相对位置

Back to Class List

Zend_Service_Yahoo_WebResultSet

Zend_Service_Yahoo_WebResultSet 代表 Yahoo! 网页搜索的结果集.

Note: Zend_Service_Yahoo_WebResultSet 扩展自 Zend_Service_Yahoo_ResultSet

Back to Class List

Zend_Service_Yahoo_ImageResultSet

Zend_Service_Yahoo_ImageResultSet 代表一个 Yahoo! 图片搜索结果集

Note: Zend_Service_Yahoo_ImageResultSet 扩展自 Zend_Service_Yahoo_ResultSet

Back to Class List

Zend_Service_Yahoo_LocalResultSet

Zend_Service_Yahoo_LocalResultSet 代表一个Yahoo!本地搜索的结果集

Zend_Service_Yahoo_LocalResultSet 属性
名称 | 类型 | 描述
resultSetMapURL | string | 包含返回查询结果地图的URL

Note: Zend_Service_Yahoo_LocalResultSet 扩展自 Zend_Service_Yahoo_ResultSet

Back to Class List

Zend_Service_Yahoo_NewsResultSet

Zend_Service_Yahoo_NewsResultSet 代表一个Yahoo!新闻搜索结果的集合

Note: Zend_Service_Yahoo_NewsResultSet 扩展自 Zend_Service_Yahoo_ResultSet

Back to Class List

Zend_Service_Yahoo_Result

每类搜索特定的结果都由这个基类扩展而成

Properties

Zend_Service_Yahoo_Result Properties
名称 | 类型 | 描述
Title | string | 结果项的标题
Url | string | 结果项的url
ClickUrl | string | 链接到结果项的url

Back to Class List

Zend_Service_Yahoo_WebResult

每一个网页搜索结果作为一个 Zend_Service_Yahoo_WebResult 对相返回.

属性

Zend_Service_Yahoo_WebResult 属性
名称 | 类型 | 描述
Summary | string | 返回结果的摘要
MimeType | string | 返回结果的mimetype
ModificationDate | string | 一个以 UNIX timestamp 表示的最后修改日期.
CacheUrl | string | 返回结果Yahoo! 网页搜索缓存页面的URL
CacheSize | int | Cache 项目的大小

Back to Class List

Zend_Service_Yahoo_ImageResult

每一个图片搜索结果作为一个 Zend_Service_Yahoo_ImageResult 对相返回.

属性

Zend_Service_Yahoo_ImageResult 属性
名称 | 类型 | 描述
Summary | string | 返回结果的摘要
RefererUrl | string | 图片引用页的URL
FileSize | int | 以bytes为单位的图片大小
FileFormat | string | 图片的格式 (bmp, gif, jpeg, png, etc.)
Height | int | 图片的高
Width | int | 图片的宽
Thumbnail | Zend_Service_Yahoo_Image | 图片的缩略图

Back to Class List

Zend_Service_Yahoo_LocalResult

每一个本地搜索结果以 Zend_Service_Yahoo_LocalResult 对相返回.

属性

Zend_Service_Yahoo_LocalResult 属性
名称 | 类型 | 描述
Address | string | 搜索结果的街道地址
City | string | 搜索结果所在的城市
State | string | 搜索结果所在的州
Phone | string | 搜索结果相关的电话号码
Rating | int | 用户对该结果的评分
Distance | float | 从你指定的位置到搜索结果的距离
MapUrl | string | 搜索结果地图的URL
BusinessUrl | string | 商务网站的URL (如果知道的话)
BusinessClickUrl | string | 链接到商务网站的URL (如果知道的话)

Back to Class List

Zend_Service_Yahoo_NewsResult

每一个新闻搜索结果作为一个 Zend_Service_Yahoo_NewsResult 对相返回.

属性

Zend_Service_Yahoo_NewsResult 属性
名称 | 类型 | 描述
Summary | string | 返回结果的摘要
NewsSource | string | 发布文章的公司
NewsSourceUrl | string | 发布文章的公司的URL
Language | string | 文章所用的语言
PublishDate | string | 用 UNIX timestamp表示的文章发布日期
ModificationDate | string | 用 UNIX timestamp表示的文章最后更新日期
Thumbnail | Zend_Service_Yahoo_Image | 文章的缩略图,如果有的话

Back to Class List

Zend_Service_Yahoo_Image

所有的Yahoo!图片和新闻搜索返回的图片都作为 Zend_Service_Yahoo_Image 对相返回

Properties

Zend_Service_Yahoo_Image Properties
名称 | 类型 | 描述
Url | string | 图片URL
Width | int | 图片的宽
Height | int | 图片的高

Back to Class List

Zend_Service_WindowsAzure
Zend_Service
Zend Framework手册 中文版
Zend_Session
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Service
  • 简介
  • Zend_Service_Akismet
  • Zend_Service_Amazon
  • Zend_Service_Amazon_Ec2
  • Zend_Service_Amazon_Ec2: Instances
  • Zend_Service_Amazon_Ec2: Windows Instances
  • Zend_Service_Amazon_Ec2: Reserved Instances
  • Zend_Service_Amazon_Ec2: CloudWatch Monitoring
  • Zend_Service_Amazon_Ec2: Amazon Machine Images (AMI)
  • Zend_Service_Amazon_Ec2: Elastic Block Stroage (EBS)
  • Zend_Service_Amazon_Ec2: Elastic IP Addresses
  • Zend_Service_Amazon_Ec2: Keypairs
  • Zend_Service_Amazon_Ec2: Regions and Availability Zones
  • Zend_Service_Amazon_Ec2: Security Groups
  • Zend_Service_Amazon_S3
  • Zend_Service_Amazon_Sqs
  • Zend_Service_Audioscrobbler
  • Zend_Service_Delicious
  • Zend_Service_DeveloperGarden
  • Zend_Service_Flickr
  • Zend_Service_LiveDocx
  • Zend_Service_Nirvanix
  • Zend_Service_ReCaptcha
  • Zend_Service_Simpy
  • Introduction
  • Zend_Service_StrikeIron
  • Zend_Service_StrikeIron: Bundled Services
  • Zend_Service_StrikeIron: Advanced Uses
  • Zend_Service_Technorati
  • Zend_Service_Twitter
  • Zend_Service_WindowsAzure
  • Zend_Service_Yahoo


Zend_Session - Zend Framework Manual

Zend_Service_Yahoo
Zend Framework Reference
Zend Framework手册 中文版
简介

Zend_Session

Table of Contents
  • 简介
  • 基本用法
  • 高级用法
  • 全局会话管理
  • Zend_Session_SaveHandler_DbTable
Zend_Service_Yahoo
Zend Framework Reference
Zend Framework手册 中文版
简介
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


简介 - Zend Framework Manual

Zend_Session
Zend_Session
Zend Framework手册 中文版
基本用法

简介

Zend Framework Auth 团队也非常期望大家在邮件列表中进行反馈和贡献： » fw-auth@lists.zend.com

在基于 PHP 开发的 Web 应用程序中，会话(session) 代表服务器端和特定的用户代理客户端(比如 web 浏览器)之间的一对一的持久的状态数据。 Zend_Session 用来在由相同客户端发起的多个页面请求之间，管理和保护会话数据 。逻辑上来说，会话数据是 cookie 数据的扩展。 和 cookie 数据不同，会话数据不储存在客户端，仅当服务器端程序源代码使得会话数据可用， 才通过回应来自客户端的请求与客户端共享会话数据。在该组件及其文档中，术语“session data”代表服务器端存储在 » $_SESSION 中的数据。该数据使用 Zend_Session 来管理，由 Zend_Session_Namespace 采用对象的方式来控制。 会话命名空间(Session Namespaces) 提供了使用经典的» 命名空间 方式来访问会话数据，命名空间逻辑上就是一系列被命名（键名为字符串）的联合数组（类似于普通的 PHP 数组）。

Zend_Session_Namespace 的实例用对象存储的方式实现了 $_SESSION 的命名空间。 Zend_Session 组件包装了PHP内置的会话模块，提供了一个管理会话的接口，也为 Zend_Session_Namespace 持久化命名空间数据提供了API。 Zend_Session_Namespace 为会话命名空间数据到PHP内部会话机制的持久化提供了一个标准的、面向对象的接口。 Zend_Session 支持现有无名的会话，同时也支持“登录会话”。Zend Framework 的用户验证组件 Zend_Auth，使用了 Zend_Session_Namespace，把用户的鉴别信息储存到了"Zend_Auth"命名空间下。 因为 Zend_Session 使用了PHP内置的会话函数，常用的配置选项和设置都仍然适用(请参考 » http://www.php.net/session)。 如此，储存在cookie或者URL中的会话标识，保持了客户端与服务器端会话状态数据之间的联系。

PHP 默认的 » session_save_handler 函数 没有解决当客户端连接到了集群服务器中的一些服务器的情况下，保持客户端与服务器端会话状态数据之间联系的问题， 因为会话状态数据只能储存在本地服务器当中（译注：也就是在各服务器间不能共享session数据）。 当一组附加的且合理的save handlers可用时，我们会提供它。我们鼓励社区成员在我们的邮件列表 » fw-auth@lists.zend.com 中发表你的建议或者提交save handlers。 与Zend_Db兼容的save handler已经发表在邮件列表中。

Zend_Session
Zend_Session
Zend Framework手册 中文版
基本用法
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Session
  • 简介
  • 基本用法
  • 高级用法
  • 全局会话管理
  • Zend_Session_SaveHandler_DbTable


基本用法 - Zend Framework Manual

简介
Zend_Session
Zend Framework手册 中文版
高级用法

基本用法

在Zend Framework中，Zend_Session_Namespace实例提供了操作会话数据主要的API。命名空间常用于隔离所有的会话数据，尽管也为所有会话数据只需要一个命名空间的情况提供了一个默认的命名空间。Zend_Session利用了PHP内置的会话模块（ext/session），以及它特有的$_SESSION全局数组做为会话状态数据的存储机制。虽然$_SESSION在PHP的全局命名空间内仍然可以访问，但是开发者不应该直接访问它，这样Zend_Session 和 Zend_Session_Namespace可以提供一组最可靠、安全的处理会话相关的功能。

每个Zend_Session_Namespace的实例对应于$_SESSION全局数组的一个条目，在那里命名空间被用作键。

<?php
require_once 'Zend/Session/Namespace.php';

$myNamespace = new Zend_Session_Namespace('myNamespace');

// $myNamespace corresponds to $_SESSION['myNamespace']
用Zend_Session直接和其它使用 $_SESSION的代码协同工作是可能的。然而，为避免问题，强烈建议这样的代码只使用$_SESSION中不和Zend_Session_Namespace的实例想对应的部分。

实例教程

在初始化Zend_Session时，如果没有指定命名空间，所有的数据将被透明地储存在'Default'命名空间下。Zend_Session不打算直接处理会话命名空间容器的内容，取而代之，我们可以使用Zend_Session_Namespace。下面的例子演示了缺省命名空间的使用，和怎样计算用户访问页面的次数：

Example #1 页面浏览计数

<?php
require_once 'Zend/Session/Namespace.php';

$defaultNamespace = new Zend_Session_Namespace('Default');

if (isset($defaultNamespace->numberOfPageRequests)) {
    $defaultNamespace->numberOfPageRequests++; // 每次页面加载，这个将递增
} else {
    $defaultNamespace->numberOfPageRequests = 1; // 第一次
}

echo "Page requests this session: ", $defaultNamespace->numberOfPageRequests;

当多个模块使用Zend_Session_Namespace的实例拥有不同的命名空间，每个模块为它自己的会话数据获得数据封装。可以传递给Zend_Session_Namespace构造函数一个可选的$namespace参数，它允许开发者分割会话数据到分离的命名空间。命名空间机制提供了一个有效的、流行的方法来确保处于命名空间之下的会话数据不遭到意外地改变。

命名空间的名称被限定为字符序列，它表示为不以下划线("_")开头的非空PHP字符串。只有Zend Framework的核心模块可使用以"Zend"开头的命名空间的名称。

Example #2 新方法： 使用命名空间避免冲突

<?php
require_once 'Zend/Session/Namespace.php';

// in the Zend_Auth component
$authNamespace = new Zend_Session_Namespace('Zend_Auth');
$authNamespace->user = "myusername";

// in a web services component
$webServiceNamespace = new Zend_Session_Namespace('Some_Web_Service');
$webServiceNamespace->user = "mywebusername";

上述例子中的代码与下面的代码有相同的效果，不过，上述例子中的会话对象把会话数据封装进了各自的命名空间。

Example #3 老方法: PHP会话访问

<?php
$_SESSION['Zend_Auth']['user'] = "myusername";
$_SESSION['Some_Web_Service']['user'] = "mywebusername";

迭代会话命名空间

Zend_Session_Namespace提供了» IteratorAggregate接口所有的能力，包括对foreach语句的支持：

Example #4 会话迭代

<?php
require_once 'Zend/Session/Namespace.php';

$aNamespace = new Zend_Session_Namespace('some_namespace_with_data_present');

foreach ($aNamespace as $index => $value) {
    echo "aNamespace->$index = '$value';\n";
}

会话命名空间的访问器

Zend_Session_Namespace实现__get(), __set(), __isset(), and __unset()这些 » 魔术方法，除了在一个子类里，这些魔术方法不能被直接调用。相反，正常的操作符自动调用这些方法，如下例所示：

Example #5 访问会话数据

<?php
require_once 'Zend/Session/Namespace.php';

$namespace = new Zend_Session_Namespace(); // 缺省的命名空间

$namespace->foo = 100;

echo "\$namespace->foo = $namespace->foo\n";

if (!isset($namespace->bar)) {
    echo "\$namespace->bar not set\n";
}

unset($namespace->foo);
简介
Zend_Session
Zend Framework手册 中文版
高级用法
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Session
  • 简介
  • 基本用法
  • 高级用法
  • 全局会话管理
  • Zend_Session_SaveHandler_DbTable


高级用法 - Zend Framework Manual

基本用法
Zend_Session
Zend Framework手册 中文版
全局会话管理

高级用法

虽然在基本用法中讲到的利用Zend框架的会话管理的方法是完全可以接受的，但还有些最佳实践需要去考虑。这一节讨论会话处理和示例Zend_Session架构的更高级用法的精彩细节。

开启会话

如何你希望所有的请求都有个由Zend_Seesion管理的会话，那么请在程序的引导文件中开启它：

Example #1 开启全局会话

<?php
require_once 'Zend/Session.php';

Zend_Session::start();

在程序的引导文件中开启会话，可以避免引发会话开启之前已经有HTTP头发向用户浏览器的异常，那样可能会破坏web页面的美观。许多高级的特性需要先执行Zend_Session::start()（更多高级的特性之后会展开）。

使用Zend_Session组件，有4种开启会话的方法，其中2种是错误的。

  1. 错误的：不要开启PHP的» session.auto_startsetting。如果你使用mode_php(或等同）并在php.ini中已经开启了该选项，而你又没有权限去关闭该选项，你可以在.htaccess文件（这个文件通常在HTML文档根目录下）中增加下面这一句：

    php_value session.auto_start 0

  2. 错误的：不要直接使用PHP的» session_start()函数。如果你直接使用session_start()，之后再使用Zend_Session_Namespace，那么Zend_Session::start()会抛出（"会话已经开始"）的异常。如果你在使用Zend_Session_Namespace或使用Zend_Session::start()后调用session_start()，那么会产生一个E_NOTICE级别的错误，且该调用将会被忽略。

  3. 正确的：使用Zend_Session::start()开启会话。如果你想让每个页面请求都开启会话，那么应该在ZF应用程序的引导文件（index.php）中尽早的调用这个函数。开启会话有些额外的开销，如果只有部分页面请求需要开启会话，那么就：

    • 在引导文件中，使用Zend_Session::setOptions()无条件地设置strict选项为true。

    • 在任何Zend_Session_Namespace()对象初始化之前对需要使用会话的请求只调用Zend_Session::start()。

    • 象往常一样，在需要会话的地方，使用"new Zend_Session_Namespace()"，但必须确认先前已经调用过Zend_Session::start()了。

    strict 选项防止 new Zend_Session_Namespace() 自动调用 Zend_Session::start()。 这样，这个选项有利于应用程序的开发者强制执行一个设计原则以避免在某些页面请求中使用会话， 因为在调用 Zend_Session::start() 之前，实例化 Zend_Session_Namespace 时，会抛出一个异常。开发者需小心地考虑使用 Zend_Session::setOptions() 所引起的冲突，由于它们对应于基本的ext/session这些具有全局作用选项。

  4. 正确的：只要有需要使用会话的地方，就初始化new Zend_Session_Namespace()，并且基本的PHP会话将自动开启。这个极端简单的用法能在大多数的情形下很好地工作。然而，如果你使用地是默认的基于cookie的会话（强烈推荐使用这种方式），你必须确保在第一次调用new Zend_Session_Namespace()在任何PHP发向向客户端输出（例如，» HTTP headers）之前。参见 错误：Headers Already Sent 有更多的信息。

锁住会话命名空间

会话的命名空间可以加锁，以防止意外的变更该命名空间下的会话变量值。使用lock()方法使某命名空间下会话变量为只读，unlock()方法使一个只读的名空间为可读写，isLocked()方法测试某命名空间是否已经被加锁。加锁是短暂的，且只在此页面请求内有效，不会持续到下一个页面请求。给命名空间加锁不会影响到存储在该命名空间下对象的setter方法，但是阻止了命名空间的setter方法的移除或替换对象。也就是说，虽给Zend_Session_Namespace的实例加了锁，但还是不能阻止它处同样引用了命名空间下数据的对它的变更（参见» PHP references)。

Example #2 锁住会话命名空间

<?php
require_once 'Zend/Session/Namespace.php';

$userProfileNamespace = new Zend_Session_Namespace('userProfileNamespace');

// 标记会话设置为只读锁定
$userProfileNamespace->lock();

// 解锁只读锁定
if ($userProfileNamespace->isLocked()) {
$userProfileNamespace->unLock();
}

命名空间过期

对于命名空间和在命名空间中的独立键，它们的寿命都是有限的。在授权后，普通用例包括在请求之间传递临时信息，和通过除去访问潜在的敏感信息来降低一定的安全风险的暴露时有发生。过期可以基于消逝的秒数或者跳步(hop)的个数，对每次初始化命名空间的成功请求，跳步至少发生一次。

Example #3 过期的例子

<?php
require_once 'Zend/Session/Namespace.php';

$s = new Zend_Session_Namespace('expireAll');
$s->a = 'apple';
$s->p = 'pear';
$s->o = 'orange';

$s->setExpirationSeconds(5, 'a'); // expire only the key "a" in 5 seconds

// 5 次访问后，会话过期
$s->setExpirationHops(5);

$s->setExpirationSeconds(60);
// 命名空间 "expireAll" 将在第一次访问后 60 秒，或者访问 5 次后过期。

在处理在当前请求中会话数据过期，需要小心来提取它们（会话数据）。尽管数据通过引用返回，修改数据将不使过期数据持续传递当前请求。为了“重置”过期时间，把数据放到临时变量，用命名空间来unset它们，然后再设置合适的键。

会话封装和控制器

命名空间可以被用来分离控制器对会话的访问，以免被污染。例如， 一个认证控制器可以为会议安全请求保持它的会话状态数据与其他控制器分离。

Example #4 带有生命期的控制器命名空间会话

下面的代码，作为显示一个测试问题的控制器的一部分，初始化一个布尔变量来表示是否一个提交的答案应该被接受。在此例中，给用户300秒时间来回答所显示的问题。

<?php
// ...
// in the question view controller
require_once 'Zend/Session/Namespace.php';
$testSpace = new Zend_Session_Namespace('testSpace');
$testSpace->setExpirationSeconds(300, 'accept_answer'); // expire only this variable
$testSpace->accept_answer = true;
//...

下面，处理测试问题答案的控制器根据用户是否在允许的时间内提交答案来决定是否接受答案：

<?php
// ...
// in the answer processing controller
require_once 'Zend/Session/Namespace.php';
$testSpace = new Zend_Session_Namespace('testSpace');
if ($testSpace->accept_answer === true) {
    // within time
}
else {
    // not within time
}
// ...

防止每个命名空间有多重实例

尽管session locking提供了很好的保护来防止意外的命名空间的会话数据的使用，Zend_Session_Namespace 也有能力防止给一个单个的命名空间创建多个实例。

为开启这个动作，当创建Zend_Session_Namespace的最后允许的实例，传递true给第二个构造函数参数。任何后来的初始化同一个命名空间的企图都会导致一个异常的抛出。

Example #5 限制命名空间访问单一实例

<?php
require_once 'Zend/Session/Namespace.php';

// create an instance of a namespace
$authSpaceAccessor1 = new Zend_Session_Namespace('Zend_Auth');

// create another instance of the same namespace, but disallow any new instances
$authSpaceAccessor2 = new Zend_Session_Namespace('Zend_Auth', true);

// making a reference is still possible
$authSpaceAccessor3 = $authSpaceAccessor2;

$authSpaceAccessor1->foo = 'bar';

assert($authSpaceAccessor2->foo, 'bar');

try {
    $aNamespaceObject = new Zend_Session_Namespace('Zend_Auth');
} catch (Zend_Session_Exception $e) {
    echo "Cannot instantiate this namespace since \$authSpaceAccessor2 was created\n";
}

上面构造函数的第二个参数告诉Zend_Session_Namespace任何之后带有"Zend_Auth"实例的命名空间都是不允许的。企图创建这样的实例导致构造函数抛出一个异常。如果在相同的请求期间稍后需要访问会话的命名空间，开发者因此有责任在其它地方给一个实例对象（在上面的例子中$authSpaceAccessor1， $authSpaceAccessor2 或者$authSpaceAccessor3）存储一个引用。例如，开发者可以存储引用到一个静态变量，添加一个引用给一个» registry （参见Zend_Registry），或者使它对其它需要访问会话命名空间的方法可用。

使用数组

在PHP 5.2.1 版本之前，因为PHP魔术方法实现的历史，修改在命名空间里的数组是不可以的。如果你只使用PHP 5.2.1 或以后的版本，那么你可以跳到下一章节。

Example #6 修改带有会话命名空间的数组数据

下面来示例问题如何被复制：

<?php
require_once 'Zend/Session/Namespace.php';
$sessionNamespace = new Zend_Session_Namespace();
$sessionNamespace->array = array();
$sessionNamespace->array['testKey'] = 1; // may not work as expected before PHP 5.2.1
echo $sessionNamespace->array['testKey'];

Example #7 在会话存储之前构造数组

如果可能，通过只在所有期望的数组值被设置后存储数组到一个会话命名空间来完全避免问题的发生。

<?php
require_once 'Zend/Session/Namespace.php';
$sessionNamespace = new Zend_Session_Namespace('Foo');
$sessionNamespace->array = array('a', 'b', 'c');

如果你正使用有影响的PHP版本并需要在分配给一个会话命名空间的键之后修改数组，你可以用下面的其中之一或者全部的方案。

Example #8 方案：重新分配一个被修改的数组

在下面的代码中，创建、修改了一个被存储的数组的拷贝，并且重新从被创建的拷贝分配位置、重写原数组。

<?php
require_once 'Zend/Session/Namespace.php';
$sessionNamespace = new Zend_Session_Namespace();

// assign the initial array
$sessionNamespace->array = array('tree' => 'apple');

// make a copy of the array
$tmp = $sessionNamespace->array;

// modfiy the array copy
$tmp['fruit'] = 'peach';

// assign a copy of the array back to the session namespace
$sessionNamespace->array = $tmp;

echo $sessionNamespace->array['fruit']; // prints "peach"

Example #9 方案：存储包括引用的数组

作为选择，存储一个包含引用的数组到期望的数组，然后直接访问它。

<?php
require_once 'Zend/Session/Namespace.php';
$myNamespace = new Zend_Session_Namespace('myNamespace');
$a = array(1, 2, 3);
$myNamespace->someArray = array( &$a );
$a['foo'] = 'bar';
echo $myNamespace->someArray['foo']; // prints "bar"

在对象中使用会话

如果你计划在PHP会话中持久对象，要知道它们将为存储被 » 系列化。这样，任何在PHP会话中持久的对象在取出时一定会从存储中被去系列化。这意味着开发者必须确保持久对象的类必须在对象从会话存储中被去系列化之前被定义。如果一个非系列化的对象的类没有被定义，那么它就变成一个stdClass的实例。

在单元测试中使用会话

Zend Framework利用PHPUnit来促进自身代码的测试。大多数开发者在他们的应用程序中，扩展已有的一组单元测试，以覆盖测试他们的代码。在运行单元测试时，如果在结束会话之后使用了写相关的方法，那么会抛出"当前Zend_Session被标记为只读"的异常。在单元测试中使用Zend_Session需要额外的注意，因为在关闭会话(Zend_Session::writeClose())，或者摧毁一个会话(Zend_Session::destroy())之后，不允许再设置或注销任何一个Zend_Session_Namespace的实例的键名了。 这样是由底层PHP的会话机制session_destroy()和session_write_close()所直接引起的，因为它未提供“撤销”机制以便单元测试setup/teardown。

围绕这一工作，参见tests/Zend/Session 中SessionTest.php和SessionTestHelper.php的单元测试testSetExpirationSeconds()，利用了PHP的exec()发起一个独立的过程。新的过程准确地模拟了一个来自浏览器的继上次之后的第二个请求。独立请求始于一个“干净”的会话，就像为任一请求执行PHP脚本。同时，要使$_SESSION[]在子过程中可更改，那么需要在父过程执行exec()之前关闭会话。

Example #10 PHPUnit Testing Code Dependent on Zend_Session

<?php
// testing setExpirationSeconds()
require_once 'tests/Zend/Session/SessionTestHelper.php'; // also see SessionTest.php
$script = 'SessionTestHelper.php';
$s = new Zend_Session_Namespace('space');
$s->a = 'apple';
$s->o = 'orange';
$s->setExpirationSeconds(5);

Zend_Session::regenerateId();
$id = Zend_Session::getId();
session_write_close(); // release session so process below can use it
sleep(4); // not long enough for things to expire
exec($script . "expireAll $id expireAll", $result);
$result = $this->sortResult($result);
$expect = ';a === apple;o === orange;p === pear';
$this->assertTrue($result === $expect,
    "iteration over default Zend_Session namespace failed; expecting result === '$expect', but got '$result'");

sleep(2); // long enough for things to expire (total of 6 seconds waiting, but expires in 5)
exec($script . "expireAll $id expireAll", $result);
$result = array_pop($result);
$this->assertTrue($result === '',
    "iteration over default Zend_Session namespace failed; expecting result === '', but got '$result')");
session_start(); // resume artificially suspended session

// We could split this into a separate test, but actually, if anything leftover from above
// contaminates the tests below, that is also a bug that we want to know about.
$s = new Zend_Session_Namespace('expireGuava');
$s->setExpirationSeconds(5, 'g'); // now try to expire only 1 of the keys in the namespace
$s->g = 'guava';
$s->p = 'peach';
$s->p = 'plum';

session_write_close(); // release session so process below can use it
sleep(6); // not long enough for things to expire
exec($script . "expireAll $id expireGuava", $result);
$result = $this->sortResult($result);
session_start(); // resume artificially suspended session
$this->assertTrue($result === ';p === plum',
    "iteration over named Zend_Session namespace failed (result=$result)");
基本用法
Zend_Session
Zend Framework手册 中文版
全局会话管理
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Session
  • 简介
  • 基本用法
  • 高级用法
  • 全局会话管理
  • Zend_Session_SaveHandler_DbTable


全局会话管理 - Zend Framework Manual

高级用法
Zend_Session
Zend Framework手册 中文版
Zend_Session_SaveHandler_DbTable

全局会话管理

会话的默认行为可以由 Zend_Session的一些静态方法来改变。使用Zend_Session来处理和操作所有的全局会话管理，包括使用Zend_Session_Core::setOptions() 方法对» PHP内置的会话模块提供的常用配置选项的配置。例如，不能确保使用安全的save_path和PHP会话模块使用的唯一的cookie名，那么使用Zend_Session::setOptions() 会引发安全问题。

配置选项

当第一个会话命名空间被请求时，Zend_Session就会自动启动PHP会话，除非已经和Zend_Session::start()一起启动了。内部PHP的会话将会按照Zend_Session的默认配置开启，除非先前调用过Zend_Session::setOptions()修改了配置。

设置会话配置选项，包括基本名（在"session."之后的名字部分）作为传递给Zend_Session::setOptions()的数组的键。数组里相应的值用来设置会话选项值。如果开发者没有设置选项，Zend_Session将首先使用推荐的缺省选项，接着就是缺省的php.ini设置。关于这些选项的最好实践的社区反馈应该发送到» fw-auth@lists.zend.com。

Example #1 使用Zend_Config配置Zend_Session

使用Zend_Config_Ini配置这个组件（Zend_Session），首先添加配置选项到INI文件：

; Accept defaults for production
[production]
; bug_compat_42
; bug_compat_warn
; cache_expire
; cache_limiter
; cookie_domain
; cookie_lifetime
; cookie_path
; cookie_secure
; entropy_file
; entropy_length
; gc_divisor
; gc_maxlifetime
; gc_probability
; hash_bits_per_character
; hash_function
; name should be unique for each PHP application sharing the same domain name
name = UNIQUE_NAME
; referer_check
; save_handler
; save_path
; serialize_handler
; use_cookies
; use_only_cookies
; use_trans_sid

; remember_me_seconds = <integer seconds>
; strict = on|off

; Development inherits configuration from production, but overrides several values
[development : production]
; Don't forget to create this directory and make it rwx (readable and modifiable) by PHP.
save_path = /home/myaccount/zend_sessions/myapp
use_only_cookies = on
; When persisting session id cookies, request a TTL of 10 days
remember_me_seconds = 864000

接着，加载配置文件并传递它的数组表达给Zend_Session::setOptions()：

<?php
require_once 'Zend/Config/Ini.php';
$config = new Zend_Config_Ini('myapp.ini', 'development');

require_once 'Zend/Session.php';
Zend_Session::setOptions($config->toArray());

上述大多数选项没有做解释，因为可以在PHP的官方文档中找到他们的解释，但这些特定的事项在下面注释。

  • boolean strict - 当使用new Zend_Session_Namespace时，禁止自动启动Zend_Session。

  • integer remember_me_seconds - 该选项指明了当用户代理结束（比如浏览器应用程序终止）后，会话标识符还将保存在cookie中的时长。

  • string save_path - 该值跟系统相关，开发者需提供一个PHP程序有读写权限的目录的绝对路径。如果可写的路径没有被提供，那么当启动时，Zend_Session 将抛出一个异常。（例如，当start()被调用）

    Note: 安全风险
     如果其他应用程序有读这个目录路径的权限，那么就有发生会话劫持的可能性。如果其他应用程序有写这个目录路径的权限，那么就有发生» 会话污染的可能性。如果这个目录路径是与其他用户或PHP应用程序共享的，那么会引起大量的安全问题，包括会话数据盗窃，会话劫持，垃圾回收冲突（举例来说，另一个用户的PHP应用程序可能会删除你的应用程序的会话文件）。
    例如，攻击者可以访问受害者的站点，获得会话cookie。在访问攻击者的站点执行var_dump($_SESSION)之前，他（攻击者）编辑cookie路径为在相同服务器上的他自己的域名。知道了有关受害者会话的详细信息，攻击者就可以修改受害者的会话状态（也就是会话中毒），把会话路径改回受害者的站点，然后使得来自受害者站点的请求使用已被污染了的会话。同个服务器上的两个应用程序不能读写对方应用程序的save_path，但如果save_path是可以猜测的，且攻击者拥有这2个站点其中一个的控制权，攻击者就可以修改他的站点会话的save_path为另一个站点的会话的save_path，从而就造成了会话污染。因此，save_path的值不能公开，且对每个应用程序必须是唯一的、安全的。

  • string name - 该值跟系统相关，开发者需为基于应用程序提供一个唯一的值。

    Note: 安全风险
     如果php.ini中session.name的值是相同的（例如，默认为“PHPSESSID”），且在同个域名下面有两个及以上的PHP应用程序，那么当访问者访问这些站点时它们共享了会话数据。此外，很可能引起会话数据的破坏。

  • boolean use_only_cookies - 为了不引入更多的安全风险，不要修改该选项的默认值。

    Note: 安全风险
     如果该选项没有被激活，攻击者使用攻击者站点上的链接，可以轻松的固定受害人的会话标识符，比如：http://www.example.com/index.php?PHPSESSID=fixed_session_id。假使受害者还没有一个example.com站点会话标识符的cookie，那么会话固定就成功了。一旦受害者使用了攻击者指定的会话标识符，那么攻击者就能劫持受害者的会话，并模仿受害者的用户代理，试图假装成受害者。

错误：Headers Already Sent

如果你看到错误信息，"Cannot modify header information - headers already sent" 或者 "You must call ... before any output has been sent to the browser; output started in ..."，那么仔细检查最近的和这信息有关联的原因（函数或方法）。任何请求发送HTTP头的动作，象发送一个cookie，必须在发送正常的输出（非缓冲输出）之前完成，除非使用PHP的输出缓冲。

  • 经常使用» output buffering就能足够防止这个问题，并帮助提高性能。例如，在php.ini里，"output_buffering = 65535"允许有64K的缓冲。即使输出缓冲在生产服务器上提高性能是一个良好的策略，仅仅依靠缓冲来解决"headers already sent"还是不够。应用程序一定不能超过缓冲的大小，否则无论什么时候输出发送（先于HTTP头）超过缓冲的大小，问题就会发生。

  • 作为选择，尝试重新安排应用程序逻辑，这样先于发送任何输出，动作处理头被执行。

  • 如果一个Zend_Session方法导致这个错误信息，仔细检查这个方法，并确保它的使用在应用程序中是必须的。例如，destroy() 缺省的用法也发送HTTP头来使客户端的会话cookie过期。如果这不是必须的，那么使用destroy(false)，因为设置cookie的指令和HTTP头一起发送。

  • 作为选择，尝试重新安排应用程序逻辑，这样先于发送任何输出，动作处理头被执行。

  • 删除任何结束"?>"标记，如果它们出现在PHP源文件的末尾。它们是必须的，并且新行和其它在结束标记之后的最近的可见的空白字符可以触发输出给客户。

会话标识符

简介：在基于ZF的应用程序中有关会话使用的问题，提倡使用浏览器的cookie是最佳的实践，而不是把会话的标识符跟在URL后面的方式来追踪用户。Zend_Session组件默认的只有cookie才能保持会话标识符。cookie的值是浏览器会话的唯一标识符。PHP内置的会话模块使用这个标识符以保持站点访问者与每个访问者的持久会话数据之间一对一的关系。Zend_Session组件包装了会话存储器（$_SESSION）并提供了一个面向对象的接口。不幸的是，如果攻击者能访问受害者的cookie值（会话标识符），攻击者就能劫持受害者的会话。这个问题不仅在PHP中存在，在Zend Framework中也存在。regenerateId()方法能使应用程序重新生成会话标识符（储存在访问者的cookie中），标识符为一个随机的、不可预计的值。注意：虽然“用户代理(user agent)”和“Web浏览器(web browser)”不相同，为了使得本章节更易读，我们使用的这两个术语可以互换。

为什么？：如果攻击者获得了受害者有效的会话标识符，攻击者就可能假扮成一个有效的用户（受害者），得到了访问机密信息或者操作受害者在你的应用程序中的数据。更新会话标识符有利于阻碍会话劫持的发生。如果会话标识符改变了，攻击者就不知道新的会话标识，也就不能用新的会话标识劫持受害者的会话了。即使攻击者能够访问旧的会话标识，regenerateId()将会话数据从旧的标识符下移到了新的标识符下，所以通过旧的会话标识符访问不到会话数据。

何时使用regenerateId()：在你的Zend框架程序引导文件中添加Zend_Session::regenerateId ()，以最安全的方式重新生成用户Web浏览器cookie中的会话标识符。如果不需要有条件的判定何时重新生成会话标识符，那么这样的方式就没什么缺陷。虽然在每个请求中重新生成会话标识预防了几种攻击的途径，但是不是每个请求需要这么做。因此，应用程序通常设法动态的确定在有较大风险的情况下，重新生成会话标识符。当站点的访问者权限上升时（比如，访问者在编辑你的个人信息前，要重新验证用户）或者敏感的会话参数发生改变时，可以考虑使用regenerateId()创建新的会话标识符。如果你调用了rememberMe()之后，就不需要调用regeneraterId()，因为前者已经调用了后者。如果用户成功登录了站点，调用rememberMe()方法来取代调用regenerateId()方法。

会话劫持和会话固定

消除» 跨站脚本攻击（XSS）漏洞有利于防止会话劫持的发生。根据» Secunia的统计，不管使用何种语言创建web应用程序，XSS问题经常发生。期望应用程序不存在跨站脚本攻击漏洞，还不如按照下面的最佳实践最小化损失，当攻击发生时。在跨站脚本攻击中，攻击者不需要直接访问受害者的网络。如果受害者已经存在一个会话 cookie，那么跨站脚本攻击的Javascript脚本会允许攻击者读取受害者的cookie并偷取会话。如果受害者还不存在会话cookie，利用跨站脚本攻击漏洞注入Javascript脚本，攻击者在受害者浏览器上创建一个已知会话标识符的cookie，然后在攻击者的系统中也创建同样的 cookie，这样就劫持受害者的会话。如果受害者访问了攻击者的站点，那么攻击者还能仿真受害者用户代理的一些其他特征。如果你的站点存在着XSS漏洞，攻击者就可能插入一段AJAX脚本，秘密的访问攻击者的站点，导致攻击者知道了受害者的浏览器特征，又知悉受害者站点的会话。然而，倘若站点开发者正确地设置了save_path选项，那么攻击者也不能任意地修改服务器端的PHP会话状态。

当第一次使用用户会话时，调用Zend_Session::regenerateId()不能防止会话固定攻击，除非你能辨别最初的会话是否是攻击者伪装成受害者。初听，这个跟前面所描述的是自相矛盾的，直到我们认为攻击者首先在你的站点上发起了一个真实的会话。如果会话第一次是被攻击者开启的，那么攻击者也就知道了初始化(regenerateId())后的结果（新的会话标识）。攻击者在XSS漏洞中使用这个新的会话标识，或者通过攻击者站点上的链接注入这个新的会话标识（只在use_only_cookies = off时有效）。

如果你能辨别使用相同会话标识符的受害者和攻击者，那么就可以直接处理会话劫持了。然而，这样的区分常常陷于可用性权衡的形式中，因为区别的方法常常是不严密的。举例来说，如果当前请求的IP与创建会话的请求的IP来自不同的国家，那么当前请求大概就是攻击者发起的。在以下的情形下，对于web应用程序就可能很难区别受害者和攻击者了：

  • - 攻击者首先在你的站点上发起一个会话，以获得一个合法的会话标识符

  • - 攻击者利用你的站点上的XSS漏洞，在受害者的浏览器上创建具有相同标识符且有效的会话cookie（也就是会话固定）

  • - 受害者和攻击者来自同一个上网代理（比如他们都处于一个大公司的同一个防火墙后面，像AOL）

下面的代码使得攻击者很难获得受害者当前的会话标识符，除非攻击者已经完成上面的第一二两步。

Example #2 会话固定

<?php
require_once 'Zend/Session/Namespace.php';
$defaultNamespace = new Zend_Session_Namespace();

if (!isset($defaultNamespace->initialized)) {
    Zend_Session::regenerateId();
    $defaultNamespace->initialized = true;
}

rememberMe(integer $seconds)

通常，用户代理结束时，会话也就结束了，比如当用户退出浏览器。然而，你的应用程序可能通过持久cookies的使用提供扩展用户会话超过客户端程序的生命期的能力。在会话被启动来控制在持久会话cookie过期之前时间的长度之前使用Zend_Session::rememberMe()。如果你没有指定秒数，那么会话cookie的生命期缺省为remember_me_seconds，它可以用Zend_Session::setOptions()来设置。为了帮助阻止会话固定/劫持，当用户成功地通过你的程序的认证，使用这个函数（例如，从一个“登录”表单）。

forgetMe()

此函数补充了rememberMe()，当用户代理终止时，写入一个有结束生命期的会话cookie。

sessionExists()

这个方法用来确定当前用户请求是否已经存在会话。这个方法可在会话开启之前使用，且这个方法独立于与Zend_Session和Zend_Session_Namespace的其他方法。

destroy(bool $remove_cookie = true, bool $readonly = true)

Zend_Session::destroy()，删除当前会话的所有数据。然而，PHP中的变量还未知情，所以你的会话命名空间（Zend_Session的实例）还是可读的。为了完成“登出”动作，设置可选的参数为true（缺省为true）来删除用户代理端的会话cookie。可选的$readonly参数删除了创建新的Zend_Session_Namespace实例和为Zend_Session方法写入会话数据存储的能力。

如果你看到错误信息"Cannot modify header information - headers already sent" ， 那么要么避免使用true 作为第一个参数（会话cookie的请求删除），要么参考错误：Headers Already Sent 。这样，Zend_Session::destroy(true) 一定要么在PHP发送HTTP头之前被调用，要么输出缓冲被允许。并且，为防止触发在调用destroy()之前发送输出，输出发送的总数不能超过缓冲的大小。

Note: Throws
 缺省地，$readonly是被激活的，之后写会话数据的动作，将会抛出一个异常。

stop()

这个方法只是更改了Zend_Session中的一个标志位，以阻止之后向会话数据存储器中写数据。我们特别希望您能反馈关于这个特性的看法。当程序的执行转移到视图相关的代码上时，以免滥用，临时关闭Zend_Session_Namespace实例和Zend_Session中的方法向会话数据存储器写数据的能力，试图通过这些实例或方法向会话数据存储器写数据的动作，都将会抛出一个异常。

writeClose($readonly = true)

关闭会话，把$_SESSION数组中的数据写到后台的存储器中（文件、数据库），完成内部数据的转换。可选的$readonly布尔参数可以通过抛出基于企图通过Zend_Session或者Zend_Session_Namespace写入会话的一个异常来删除写的能力。

Note: Throws
 缺省地，$readonly是被激活的，之后向会话数据存储器写数据的动作讲抛出异常。然而，一些遗留的应用程序期望$_SESSION在会话通过session_write_close()关闭后仍然可以写。虽然不是最佳的实践，但$readonly选项对有需要的人还是有用的。

expireSessionCookie()

该方法向客户端发送一个过期的会话cookie，以引起客户端删除会话cookie。通常这个技术被用来执行客户端登出请求。

setSaveHandler(Zend_Session_SaveHandler_Interface $interface)

对于大多数开发者来说缺省的save handler已经足够了。这个方法只是以面向对象的方式包装了一下» session_set_save_handler()函数。

namespaceIsset($namespace)

这个方法用来检查某会话命名空间是否存在，或者某会话命名空间下的某个索引是否存在。

Note: Throws
 如果Zend_Session没有被标记为可读（比如在Zend_Session开启之前），将会抛出一个异常。

namespaceUnset($namespace)

使用namespaceUnset($namespace)注销某个命名空间及其内容，而不用为某个命名空间创建Zend_Session实例，然后迭代它删除每个条目。如果被注销的变量为数组，且该数组包含了其他对象，而这些对象又被其他变量引用，这些对象仍然是可访问的。不要期望namespaceUnset方法会“深”注销/删除命名空间下条目的内容。更详细的解释，请参考PHP手册中的» References Explained

Note: Throws
 如果命名空间不可读（比如执行了destroy()之后），将会抛出一个异常。

namespaceGet($namespace)

不赞成的：在Zend_Session_Namespace中用getIterator()。 这个方法返回$namespace命名空间的内容数组$name。如果你有合理的理由认为该方法是公有的，请反馈到我们的邮件列表：» fw-auth@lists.zend.com。实际上，所有参与相关话题讨论的，我们都是欢迎的。

Note: Throws
 如果Zend_Session没有被标记为可读（比如在Zend_Session开启之前），将会抛出一个异常。

getIterator()

使用getIterator()方法，可获得一个包含所有命名空间名字的数组。

Note: Throws
 如果Zend_Session没有被标记为可读（比如在Zend_Session开启之前），将会抛出一个异常。

高级用法
Zend_Session
Zend Framework手册 中文版
Zend_Session_SaveHandler_DbTable
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Session
  • 简介
  • 基本用法
  • 高级用法
  • 全局会话管理
  • Zend_Session_SaveHandler_DbTable


Zend_Session_SaveHandler_DbTable - Zend Framework Manual

全局会话管理
Zend_Session
Zend Framework手册 中文版
Zend_Soap

Zend_Session_SaveHandler_DbTable

The basic setup for Zend_Session_SaveHandler_DbTable must at least have four columns, denoted in the config array or Zend_Config object: primary, which is the primary key and defaults to just the session id which by default is a string of length 32; modified, which is the unix timestamp of the last modified date; lifetime, which is the lifetime of the session (modified + lifetime > time();); and data, which is the serialized data stored in the session

Example #1 Basic Setup

  1. CREATE TABLE `session` (
  2.   `id` char(32),
  3.   `modified` int,
  4.   `lifetime` int,
  5.   `data` text,
  6.   PRIMARY KEY (`id`)
  7. );
  1. //get your database connection ready
  2. $db = Zend_Db::factory('Pdo_Mysql', array(
  3.     'host'        =>'example.com',
  4.     'username'    => 'dbuser',
  5.     'password'    => '******',
  6.     'dbname'    => 'dbname'
  7. ));
  8.
  9. //you can either set the Zend_Db_Table default adapter
  10. //or you can pass the db connection straight to the save handler $config
  11. Zend_Db_Table_Abstract::setDefaultAdapter($db);
  12. $config = array(
  13.     'name'           => 'session',
  14.     'primary'        => 'id',
  15.     'modifiedColumn' => 'modified',
  16.     'dataColumn'     => 'data',
  17.     'lifetimeColumn' => 'lifetime'
  18. );
  19.
  20. //create your Zend_Session_SaveHandler_DbTable and
  21. //set the save handler for Zend_Session
  22. Zend_Session::setSaveHandler(new Zend_Session_SaveHandler_DbTable($config));
  23.
  24. //start your session!
  25. Zend_Session::start();
  26.
  27. //now you can use Zend_Session like any other time

You can also use Multiple Columns in your primary key for Zend_Session_SaveHandler_DbTable.

Example #2 Using a Multi-Column Primary Key

  1. CREATE TABLE `session` (
  2.     `session_id` char(32) NOT NULL,
  3.     `save_path` varchar(32) NOT NULL,
  4.     `name` varchar(32) NOT NULL DEFAULT '',
  5.     `modified` int,
  6.     `lifetime` int,
  7.     `session_data` text,
  8.     PRIMARY KEY (`Session_ID`, `save_path`, `name`)
  9. );
  1. //setup your DB connection like before
  2. //NOTE: this config is also passed to Zend_Db_Table so anything specific
  3. //to the table can be put in the config as well
  4. $config = array(
  5.     'name'              => 'session', //table name as per Zend_Db_Table
  6.     'primary'           => array(
  7.         'session_id',   //the sessionID given by PHP
  8.         'save_path',    //session.save_path
  9.         'name',         //session name
  10.     ),
  11.     'primaryAssignment' => array(
  12.         //you must tell the save handler which columns you
  13.         //are using as the primary key. ORDER IS IMPORTANT
  14.         'sessionId', //first column of the primary key is of the sessionID
  15.         'sessionSavePath', //second column of the primary key is the save path
  16.         'sessionName', //third column of the primary key is the session name
  17.     ),
  18.     'modifiedColumn'    => 'modified',     //time the session should expire
  19.     'dataColumn'        => 'session_data', //serialized data
  20.     'lifetimeColumn'    => 'lifetime',     //end of life for a specific record
  21. );
  22.
  23. //Tell Zend_Session to use your Save Handler
  24. Zend_Session::setSaveHandler(new Zend_Session_SaveHandler_DbTable($config));
  25.
  26. //start your session
  27. Zend_Session::start();
  28.
  29. //use Zend_Session as normal
全局会话管理
Zend_Session
Zend Framework手册 中文版
Zend_Soap
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Session
  • 简介
  • 基本用法
  • 高级用法
  • 全局会话管理
  • Zend_Session_SaveHandler_DbTable


Zend_Soap - Zend Framework Manual

Zend_Session_SaveHandler_DbTable
Zend Framework Reference
Zend Framework手册 中文版
Zend_Soap_Server

Zend_Soap

Table of Contents
  • Zend_Soap_Server
  • Zend_Soap_Client
  • WSDL Accessor
  • AutoDiscovery
Zend_Session_SaveHandler_DbTable
Zend Framework Reference
Zend Framework手册 中文版
Zend_Soap_Server
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


Zend_Soap_Server - Zend Framework Manual

Zend_Soap
Zend_Soap
Zend Framework手册 中文版
Zend_Soap_Client

Zend_Soap_Server

Zend_Soap_Server class is intended to simplify Web Services server part development for PHP programmers.

It may be used in WSDL or non-WSDL mode, and using classes or functions to define Web Service API.

When Zend_Soap_Server component works in the WSDL mode, it uses already prepared WSDL document to define server object behavior and transport layer options.

WSDL document may be auto-generated with functionality provided by Zend_Soap_AutoDiscovery component or should be constructed manually using Zend_Soap_Wsdl class or any other XML generating tool.

If the non-WSDL mode is used, then all protocol options have to be set using options mechanism.

Zend_Soap_Server constructor

Zend_Soap_Server constructor should be used a bit differently for WSDL and non-WSDL modes.

Zend_Soap_Server constructor for the WSDL mode

Zend_Soap_Server constructor takes two optional parameters when it works in WSDL mode:

  1. $wsdl, which is an URI of a WSDL file[1] setWsdl($wsdl) .

  2. $options - options to create SOAP server object[2] setOptions($options) .

    The following options are recognized in the WSDL mode:

    • 'soap_version' ('soapVersion') - soap version to use (SOAP_1_1 or SOAP_1_2).

    • 'actor' - the actor URI for the server.

    • 'classmap' ('classMap') which can be used to map some WSDL types to PHP classes.

      The option must be an array with WSDL types as keys and names of PHP classes as values.

    • 'encoding' - internal character encoding (UTF-8 is always used as an external encoding).

    • 'wsdl' which is equivalent to setWsdl($wsdlValue) call.

Zend_Soap_Server constructor for the non-WSDL mode

The first constructor parameter must be set to NULL if you plan to use Zend_Soap_Server functionality in non-WSDL mode.

You also have to set 'uri' option in this case (see below).

The second constructor parameter ($options) is an array with options to create SOAP server object[3] setOptions($options) .

The following options are recognized in the non-WSDL mode:

  • 'soap_version' ('soapVersion') - soap version to use (SOAP_1_1 or SOAP_1_2).

  • 'actor' - the actor URI for the server.

  • 'classmap' ('classMap') which can be used to map some WSDL types to PHP classes.

    The option must be an array with WSDL types as keys and names of PHP classes as values.

  • 'encoding' - internal character encoding (UTF-8 is always used as an external encoding).

  • 'uri' (required) - URI namespace for SOAP server.

Methods to define Web Service API

There are two ways to define Web Service API when your want to give access to your PHP code through SOAP.

The first one is to attach some class to the Zend_Soap_Server object which has to completely describe Web Service API:

  1. ...
  2. class MyClass {
  3.     /**
  4.      * This method takes ...
  5.      *
  6.      * @param integer $inputParam
  7.      * @return string
  8.      */
  9.     public function method1($inputParam) {
  10.         ...
  11.     }
  12.
  13.     /**
  14.      * This method takes ...
  15.      *
  16.      * @param integer $inputParam1
  17.      * @param string  $inputParam2
  18.      * @return float
  19.      */
  20.     public function method2($inputParam1, $inputParam2) {
  21.         ...
  22.     }
  23.
  24.     ...
  25. }
  26. ...
  27. $server = new Zend_Soap_Server(null, $options);
  28. // Bind Class to Soap Server
  29. $server->setClass('MyClass');
  30. // Bind already initialized object to Soap Server
  31. $server->setObject(new MyClass());
  32. ...
  33. $server->handle();

Note: Important!
 You should completely describe each method using method docblock if you plan to use autodiscover functionality to prepare corresponding Web Service WSDL.

The second method of defining Web Service API is using set of functions and addFunction() or loadFunctions() methods:

  1. ...
  2. /**
  3. * This function ...
  4. *
  5. * @param integer $inputParam
  6. * @return string
  7. */
  8. function function1($inputParam) {
  9.     ...
  10. }
  11.
  12. /**
  13. * This function ...
  14. *
  15. * @param integer $inputParam1
  16. * @param string  $inputParam2
  17. * @return float
  18. */
  19. function function2($inputParam1, $inputParam2) {
  20.     ...
  21. }
  22. ...
  23. $server = new Zend_Soap_Server(null, $options);
  24. $server->addFunction('function1');
  25. $server->addFunction('function2');
  26. ...
  27. $server->handle();

Request and response objects handling

Note: Advanced
 This section describes advanced request/response processing options and may be skipped.

Zend_Soap_Server component performs request/response processing automatically, but allows to catch it and do some pre- and post-processing.

Request processing

Zend_Soap_Server::handle() method takes request from the standard input stream ('php://input'). It may be overridden either by supplying optional parameter to the handle() method or by setting request using setRequest() method:

  1. ...
  2. $server = new Zend_Soap_Server(...);
  3. ...
  4. // Set request using optional $request parameter
  5. $server->handle($request);
  6. ...
  7. // Set request using setRequest() method
  8. $server->setRequest();
  9. $server->handle();

Request object may be represented using any of the following:

  • DOMDocument (casted to XML)

  • DOMNode (owner document is grabbed and casted to XML)

  • SimpleXMLElement (casted to XML)

  • stdClass (__toString() is called and verified to be valid XML)

  • string (verified to be valid XML)

Last processed request may be retrieved using getLastRequest() method as an XML string:

  1. ...
  2. $server = new Zend_Soap_Server(...);
  3. ...
  4. $server->handle();
  5. $request = $server->getLastRequest();

Response pre-processing

Zend_Soap_Server::handle() method automatically emits generated response to the output stream. It may be blocked using setReturnResponse() with TRUE or FALSE as a parameter[4] setReturnResponse() . Generated response is returned by handle() method in this case.

  1. ...
  2. $server = new Zend_Soap_Server(...);
  3. ...
  4. // Get a response as a return value of handle() method
  5. // instead of emitting it to the standard output
  6. $server->setReturnResponse(true);
  7. ...
  8. $response = $server->handle();
  9. ...

Last response may be also retrieved by getLastResponse() method for some post-processing:

  1. ...
  2. $server = new Zend_Soap_Server(...);
  3. ...
  4. $server->handle();
  5. $response = $server->getLastResponse();
  6. ...

[1] May be set later using method.
[2] Options may be set later using method.
[3] Options may be set later using method.
[4] Current state of the Return Response flag may be requested with method.
Zend_Soap
Zend_Soap
Zend Framework手册 中文版
Zend_Soap_Client
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Soap
  • Zend_Soap_Server
  • Zend_Soap_Client
  • WSDL Accessor
  • AutoDiscovery


Zend_Soap_Client - Zend Framework Manual

Zend_Soap_Server
Zend_Soap
Zend Framework手册 中文版
WSDL Accessor

Zend_Soap_Client

The Zend_Soap_Client class simplifies SOAP client development for PHP programmers.

It may be used in WSDL or non-WSDL mode.

Under the WSDL mode, the Zend_Soap_Client component uses a WSDL document to define transport layer options.

The WSDL description is usually provided by the web service the client will access. If the WSDL description is not made available, you may want to use Zend_Soap_Client in non-WSDL mode. Under this mode, all SOAP protocol options have to be set explicitly on the Zend_Soap_Client class.

Zend_Soap_Client Constructor

The Zend_Soap_Client constructor takes two parameters:

  • $wsdl - the URI of a WSDL file.

  • $options - options to create SOAP client object.

Both of these parameters may be set later using setWsdl($wsdl) and setOptions($options) methods respectively.

Note: Important!
 If you use Zend_Soap_Client component in non-WSDL mode, you must set the 'location' and 'uri' options.

The following options are recognized:

  • 'soap_version' ('soapVersion') - soap version to use (SOAP_1_1 or SOAP_1_2).

  • 'classmap' ('classMap') - can be used to map some WSDL types to PHP classes.

    The option must be an array with WSDL types as keys and names of PHP classes as values.

  • 'encoding' - internal character encoding (UTF-8 is always used as an external encoding).

  • 'wsdl' which is equivalent to setWsdl($wsdlValue) call.

    Changing this option may switch Zend_Soap_Client object to or from WSDL mode.

  • 'uri' - target namespace for the SOAP service (required for non-WSDL-mode, doesn't work for WSDL mode).

  • 'location' - the URL to request (required for non-WSDL-mode, doesn't work for WSDL mode).

  • 'style' - request style (doesn't work for WSDL mode): SOAP_RPC or SOAP_DOCUMENT.

  • 'use' - method to encode messages (doesn't work for WSDL mode): SOAP_ENCODED or SOAP_LITERAL.

  • 'login' and 'password' - login and password for an HTTP authentication.

  • 'proxy_host', 'proxy_port', 'proxy_login', and 'proxy_password' - an HTTP connection through a proxy server.

  • 'local_cert' and 'passphrase' - HTTPS client certificate authentication options.

  • 'compression' - compression options; it's a combination of SOAP_COMPRESSION_ACCEPT, SOAP_COMPRESSION_GZIP and SOAP_COMPRESSION_DEFLATE options which may be used like this:

    1. // Accept response compression
    2. $client = new Zend_Soap_Client("some.wsdl",
    3.   array('compression' => SOAP_COMPRESSION_ACCEPT));
    4. ...
    5.
    6. // Compress requests using gzip with compression level 5
    7. $client = new Zend_Soap_Client("some.wsdl",
    8.   array('compression' => SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP | 5));
    9. ...
    10.
    11. // Compress requests using deflate compression
    12. $client = new Zend_Soap_Client("some.wsdl",
    13.   array('compression' => SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_DEFLATE));

Performing SOAP Requests

After we've created a Zend_Soap_Client object we are ready to perform SOAP requests.

Each web service method is mapped to the virtual Zend_Soap_Client object method which takes parameters with common PHP types.

Use it like in the following example:

  1. //****************************************************************
  2. //                Server code
  3. //****************************************************************
  4. // class MyClass {
  5. //     /**
  6. //      * This method takes ...
  7. //      *
  8. //      * @param integer $inputParam
  9. //      * @return string
  10. //      */
  11. //     public function method1($inputParam) {
  12. //         ...
  13. //     }
  14. //
  15. //     /**
  16. //      * This method takes ...
  17. //      *
  18. //      * @param integer $inputParam1
  19. //      * @param string  $inputParam2
  20. //      * @return float
  21. //      */
  22. //     public function method2($inputParam1, $inputParam2) {
  23. //         ...
  24. //     }
  25. //
  26. //     ...
  27. // }
  28. // ...
  29. // $server = new Zend_Soap_Server(null, $options);
  30. // $server->setClass('MyClass');
  31. // ...
  32. // $server->handle();
  33. //
  34. //****************************************************************
  35. //                End of server code
  36. //****************************************************************
  37.
  38. $client = new Zend_Soap_Client("MyService.wsdl");
  39. ...
  40.
  41. // $result1 is a string
  42. $result1 = $client->method1(10);
  43. ...
  44.
  45. // $result2 is a float
  46. $result2 = $client->method2(22, 'some string');

Zend_Soap_Server
Zend_Soap
Zend Framework手册 中文版
WSDL Accessor
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Soap
  • Zend_Soap_Server
  • Zend_Soap_Client
  • WSDL Accessor
  • AutoDiscovery


WSDL Accessor - Zend Framework Manual

Zend_Soap_Client
Zend_Soap
Zend Framework手册 中文版
AutoDiscovery

WSDL Accessor

Note: Zend_Soap_Wsdl class is used by Zend_Soap_Server component internally to operate with WSDL documents. Nevertheless, you could also use functionality provided by this class for your own needs. The Zend_Soap_Wsdl package contains both a parser and a builder of WSDL documents.
If you don't plan to do this, you can skip this documentation section.

Zend_Soap_Wsdl constructor

Zend_Soap_Wsdl constructor takes three parameters:

  1. $name - name of the Web Service being described.
  2. $uri - URI where the WSDL will be available (could also be a reference to the file in the filesystem.)
  3. $strategy - optional flag used to identify the strategy for complex types (objects) detection. This was a boolean $extractComplexTypes before version 1.7 and can still be set as a boolean for backwards compatibility. By default the 1.6 detection behaviour is set. To read more on complex type detection strategies go to the section: Adding complex type information.

addMessage() method

addMessage($name, $parts) method adds new message description to the WSDL document (/definitions/message element).

Each message correspond to methods in terms of Zend_Soap_Server and Zend_Soap_Client functionality.

$name parameter represents message name.

$parts parameter is an array of message parts which describe SOAP call parameters. It's an associative array: 'part name' (SOAP call parameter name) => 'part type'.

Type mapping management is performed using addTypes(), addTypes() and addComplexType() methods (see below).

Note: Messages parts can use either 'element' or 'type' attribute for typing (see http://www.w3.org/TR/wsdl#_messages).
'element' attribute must refer to a corresponding element of data type definition. 'type' attribute refers to a corresponding complexType entry.
All standard XSD types have both 'element' and 'complexType' definitions (see http://schemas.xmlsoap.org/soap/encoding/).
All non-standard types, which may be added using Zend_Soap_Wsdl::addComplexType() method, are described using 'complexType' node of '/definitions/types/schema/' section of WSDL document.
So addMessage() method always uses 'type' attribute to describe types.

addPortType() method

addPortType($name) method adds new port type to the WSDL document (/definitions/portType) with the specified port type name.

It joins a set of Web Service methods defined in terms of Zend_Soap_Server implementation.

See http://www.w3.org/TR/wsdl#_porttypes for the details.

addPortOperation() method

addPortOperation($portType, $name, $input = false, $output = false, $fault = false) method adds new port operation to the specified port type of the WSDL document (/definitions/portType/operation).

Each port operation corresponds to a class method (if Web Service is based on a class) or function (if Web Service is based on a set of methods) in terms of Zend_Soap_Server implementation.

It also adds corresponding port operation messages depending on specified $input, $output and $fault parameters.

Note: Zend_Soap_Server component generates two messages for each port operation while describing service based on Zend_Soap_Server class:

  • input message with name $methodName . 'Request'.

  • output message with name $methodName . 'Response'.

See http://www.w3.org/TR/wsdl#_request-response for the details.

addBinding() method

addBinding($name, $portType) method adds new binding to the WSDL document (/definitions/binding).

'binding' WSDL document node defines message format and protocol details for operations and messages defined by a particular portType (see http://www.w3.org/TR/wsdl#_bindings).

The method creates binding node and returns it. Then it may be used to fill with actual data.

Zend_Soap_Server implementation uses $serviceName . 'Binding' name for 'binding' element of WSDL document.

addBindingOperation() method

addBindingOperation($binding, $name, $input = false, $output = false, $fault = false) method adds an operation to a binding element (/definitions/binding/operation) with the specified name.

It takes XML_Tree_Node object returned by addBinding() as an input ($binding parameter) to add 'operation' element with input/output/false entries depending on specified parameters

Zend_Soap_Server implementation adds corresponding binding entry for each Web Service method with input and output entries defining 'soap:body' element as '<soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>

See http://www.w3.org/TR/wsdl#_bindings for the details.

addSoapBinding() method

addSoapBinding($binding, $style = 'document', $transport = 'http://schemas.xmlsoap.org/soap/http') method adds SOAP binding ('soap:binding') entry to the binding element (which is already linked to some port type) with the specified style and transport (Zend_Soap_Server implementation uses RPC style over HTTP).

'/definitions/binding/soap:binding' element is used to signify that the binding is bound to the SOAP protocol format.

See http://www.w3.org/TR/wsdl#_bindings for the details.

addSoapOperation() method

addSoapOperation($binding, $soap_action) method adds SOAP operation ('soap:operation') entry to the binding element with the specified action. 'style' attribute of the 'soap:operation' element is not used since programming model (RPC-oriented or document-oriented) may be using addSoapBinding() method

'soapAction' attribute of '/definitions/binding/soap:operation' element specifies the value of the SOAPAction header for this operation. This attribute is required for SOAP over HTTP and must not be specified for other transports.

Zend_Soap_Server implementation uses $serviceUri . '#' . $methodName for SOAP operation action name.

See http://www.w3.org/TR/wsdl#_soap:operation for the details.

addService() method

addService($name, $port_name, $binding, $location) method adds '/definitions/service' element to the WSDL document with the specified Wed Service name, port name, binding, and location.

WSDL 1.1 allows to have several port types (sets of operations) per service. This ability is not used by Zend_Soap_Server implementation and not supported by Zend_Soap_Wsdl class.

Zend_Soap_Server implementation uses:

  • $name . 'Service' as a Web Service name,

  • $name . 'Port' as a port type name,

  • 'tns:' . $name . 'Binding' [1] 'tns:' namespace URI'http://' .$_SERVER['HTTP_HOST'] . $_SERVER['SCRIPT_NAME'] as binding name,

  • script URI [2] 'http://' .$_SERVER['HTTP_HOST'] . $_SERVER['SCRIPT_NAME'] as a service URI for Web Service definition using classes.

where $name is a class name for the Web Service definition mode using class and script name for the Web Service definition mode using set of functions.

See http://www.w3.org/TR/wsdl#_services for the details.

Type mapping

Zend_Soap WSDL accessor implementation uses the following type mapping between PHP and SOAP types:

  • PHP strings <-> xsd:string.

  • PHP integers <-> xsd:int.

  • PHP floats and doubles <-> xsd:float.

  • PHP booleans <-> xsd:boolean.

  • PHP arrays <-> soap-enc:Array.

  • PHP object <-> xsd:struct.

  • PHP class <-> based on complex type strategy (See: Adding complex type information) [3] Zend_Soap_WsdlZend_Soap_Wsdl_Strategy_DefaultComplexTypeZend_Soap_Wsdl_Strategy_Interface$extractComplexType Zend_Soap_Wsdl_Strategy_DefaultComplexType Zend_Soap_Wsdl_Strategy_AnyType .

  • PHP void <-> empty type.

  • If type is not matched to any of these types by some reason, then xsd:anyType is used.

Where xsd: is "http://www.w3.org/2001/XMLSchema" namespace, soap-enc: is a "http://schemas.xmlsoap.org/soap/encoding/" namespace, tns: is a "target namespace" for a service.

Retrieving type information

getType($type) method may be used to get mapping for a specified PHP type:

  1. ...
  2. $wsdl = new Zend_Soap_Wsdl('My_Web_Service', $myWebServiceUri);
  3.
  4. ...
  5. $soapIntType = $wsdl->getType('int');
  6.
  7. ...
  8. class MyClass {
  9.     ...
  10. }
  11. ...
  12. $soapMyClassType = $wsdl->getType('MyClass');

Adding complex type information

addComplexType($type) method is used to add complex types (PHP classes) to a WSDL document.

It's automatically used by getType() method to add corresponding complex types of method parameters or return types.

Its detection and building algorithm is based on the currently active detection strategy for complex types. You can set the detection strategy either by specifying the class name as string or instance of a Zend_Soap_Wsdl_Strategy_Interface implementation as the third parameter of the constructor or using the setComplexTypeStrategy($strategy) function of Zend_Soap_Wsdl. The following detection strategies currently exist:

  • Class Zend_Soap_Wsdl_Strategy_DefaultComplexType: Enabled by default (when no third constructor parameter is set). Iterates over the public attributes of a class type and registers them as subtypes of the complex object type.

  • Class Zend_Soap_Wsdl_Strategy_AnyType: Casts all complex types into the simple XSD type xsd:anyType. Be careful this shortcut for complex type detection can probably only be handled successfully by weakly typed languages such as PHP.

  • Class Zend_Soap_Wsdl_Strategy_ArrayOfTypeSequence: This strategy allows to specify return parameters of the type: int[] or string[]. As of Zend Framework version 1.9 it can handle both simple PHP types such as int, string, boolean, float aswell as objects and arrays of objects.

  • Class Zend_Soap_Wsdl_Strategy_ArrayOfTypeComplex: This strategy allows to detect very complex arrays of objects. Objects types are detected based on the Zend_Soap_Wsdl_Strategy_DefaultComplexType and an array is wrapped around that definition.

  • Class Zend_Soap_Wsdl_Strategy_Composite: This strategy can combine all strategies by connecting PHP Complex types (Classnames) to the desired strategy via the connectTypeToStrategy($type, $strategy) method. A complete typemap can be given to the constructor as an array with $type -> $strategy pairs. The second parameter specifies the default strategy that will be used if an unknown type is requested for adding. This parameter defaults to the Zend_Soap_Wsdl_Strategy_DefaultComplexType strategy.

addComplexType() method creates '/definitions/types/xsd:schema/xsd:complexType' element for each described complex type with name of the specified PHP class.

Class property MUST have docblock section with the described PHP type to have property included into WSDL description.

addComplexType() checks if type is already described within types section of the WSDL document.

It prevents duplications if this method is called two or more times and recursion in the types definition section.

See http://www.w3.org/TR/wsdl#_types for the details.

addDocumentation() method

addDocumentation($input_node, $documentation) method adds human readable documentation using optional 'wsdl:document' element.

'/definitions/binding/soap:binding' element is used to signify that the binding is bound to the SOAP protocol format.

See http://www.w3.org/TR/wsdl#_documentation for the details.

Get finalized WSDL document

toXML(), toDomDocument() and dump($filename = false) methods may be used to get WSDL document as an XML, DOM structure or a file.

[1] is defined as script ().
[2]
[3] By default will be created with the class as detection algorithm for complex types. The first parameter of the AutoDiscover constructor takes any complex type strategy implementing or a string with the name of the class. For backwards compatibility with boolean variables are parsed the following way: If TRUE, , if FALSE.
Zend_Soap_Client
Zend_Soap
Zend Framework手册 中文版
AutoDiscovery
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Soap
  • Zend_Soap_Server
  • Zend_Soap_Client
  • WSDL Accessor
  • AutoDiscovery


AutoDiscovery - Zend Framework Manual

WSDL Accessor
Zend_Soap
Zend Framework手册 中文版
Zend_Tag

AutoDiscovery

AutoDiscovery Introduction

SOAP functionality implemented within Zend Framework is intended to make all steps required for SOAP communications more simple.

SOAP is language independent protocol. So it may be used not only for PHP-to-PHP communications.

There are three configurations for SOAP applications where Zend Framework may be utilized:

  1. SOAP server PHP application <---> SOAP client PHP application
  2. SOAP server non-PHP application <---> SOAP client PHP application
  3. SOAP server PHP application <---> SOAP client non-PHP application

We always have to know, which functionality is provided by SOAP server to operate with it. » WSDL is used to describe network service API in details.

WSDL language is complex enough (see » http://www.w3.org/TR/wsdl for the details). So it's difficult to prepare correct WSDL description.

Another problem is synchronizing changes in network service API with already existing WSDL.

Both these problem may be solved by WSDL autogeneration. A prerequisite for this is a SOAP server autodiscovery. It constructs object similar to object used in SOAP server application, extracts necessary information and generates correct WSDL using this information.

There are two ways for using Zend Framework for SOAP server application:

  • Use separated class.

  • Use set of functions

Both methods are supported by Zend Framework Autodiscovery functionality.

TheZend_Soap_AutoDiscover class also supports datatypes mapping from PHP to » XSD types.

Here is an example of common usage of the autodiscovery functionality. The handle() function generates the WSDL file and posts it to the browser.

  1. class My_SoapServer_Class {
  2. ...
  3. }
  4.
  5. $autodiscover = new Zend_Soap_AutoDiscover();
  6. $autodiscover->setClass('My_SoapServer_Class');
  7. $autodiscover->handle();

If you need access to the generated WSDL file either to save it to a file or as an XML string you can use the dump($filename) or toXml() functions the AutoDiscover class provides.

Note: Zend_Soap_Autodiscover is not a Soap Server
 It is very important to note, that the class Zend_Soap_AutoDiscover does not act as a SOAP Server on its own. It only generates the WSDL and serves it to anyone accessing the url it is listening on.
As the SOAP Endpoint Uri is uses the default 'http://' .$_SERVER['HTTP_HOST'] . $_SERVER['SCRIPT_NAME'], but this can be changed with the setUri() function or the Constructor parameter of Zend_Soap_AutoDiscover class. The endpoint has to provide a Zend_Soap_Server that listens to requests.

  1. if(isset($_GET['wsdl'])) {
  2.     $autodiscover = new Zend_Soap_AutoDiscover();
  3.     $autodiscover->setClass('HelloWorldService');
  4.     $autodiscover->handle();
  5. } else {
  6.     // pointing to the current file here
  7.     $soap = new Zend_Soap_Server("http://example.com/soap.php?wsdl");
  8.     $soap->setClass('HelloWorldService');
  9.     $soap->handle();
  10. }

Class autodiscovering

If class is used to provide SOAP server functionality, then the same class should be provided to Zend_Soap_AutoDiscover for WSDL generation:

  1. $autodiscover = new Zend_Soap_AutoDiscover();
  2. $autodiscover->setClass('My_SoapServer_Class');
  3. $autodiscover->handle();

The following rules are used while WSDL generation:

  • Generated WSDL describes an RPC style Web Service.

  • Class name is used as a name of the Web Service being described.

  • 'http://' .$_SERVER['HTTP_HOST'] . $_SERVER['SCRIPT_NAME'] is used as an URI where the WSDL is available by default but can be overwritten via setUri() method.

    It's also used as a target namespace for all service related names (including described complex types).

  • Class methods are joined into one » Port Type.

    $className . 'Port' is used as Port Type name.

  • Each class method is registered as a corresponding port operation.

  • Each method prototype generates corresponding Request/Response messages.

    Method may have several prototypes if some method parameters are optional.

Note: Important!
 WSDL autodiscovery utilizes the PHP docblocks provided by the developer to determine the parameter and return types. In fact, for scalar types, this is the only way to determine the parameter types, and for return types, this is the only way to determine them.
That means, providing correct and fully detailed docblocks is not only best practice, but is required for discovered class.

Functions autodiscovering

If set of functions are used to provide SOAP server functionality, then the same set should be provided to Zend_Soap_AutoDiscovery for WSDL generation:

  1. $autodiscover = new Zend_Soap_AutoDiscover();
  2. $autodiscover->addFunction('function1');
  3. $autodiscover->addFunction('function2');
  4. $autodiscover->addFunction('function3');
  5. ...
  6. $autodiscover->handle();

The following rules are used while WSDL generation:

  • Generated WSDL describes an RPC style Web Service.

  • Current script name is used as a name of the Web Service being described.

  • 'http://' .$_SERVER['HTTP_HOST'] . $_SERVER['SCRIPT_NAME'] is used as an URI where the WSDL is available.

    It's also used as a target namespace for all service related names (including described complex types).

  • Functions are joined into one » Port Type.

    $functionName . 'Port' is used as Port Type name.

  • Each function is registered as a corresponding port operation.

  • Each function prototype generates corresponding Request/Response messages.

    Function may have several prototypes if some method parameters are optional.

Note: Important!
 WSDL autodiscovery utilizes the PHP docblocks provided by the developer to determine the parameter and return types. In fact, for scalar types, this is the only way to determine the parameter types, and for return types, this is the only way to determine them.
That means, providing correct and fully detailed docblocks is not only best practice, but is required for discovered class.

Autodiscovering Datatypes

Input/output datatypes are converted into network service types using the following mapping:

  • PHP strings <-> xsd:string.

  • PHP integers <-> xsd:int.

  • PHP floats and doubles <-> xsd:float.

  • PHP booleans <-> xsd:boolean.

  • PHP arrays <-> soap-enc:Array.

  • PHP object <-> xsd:struct.

  • PHP class <-> based on complex type strategy (See: Adding complex type information) [1] Zend_Soap_AutoDiscoverZend_Soap_Wsdl_Strategy_DefaultComplexTypeZend_Soap_Wsdl_Strategy_Interface$extractComplexType Zend_Soap_Wsdl Zend_Soap_Wsdl manual on adding complex .

  • type[] or object[] (ie. int[]) <-> based on complex type strategy

  • PHP void <-> empty type.

  • If type is not matched to any of these types by some reason, then xsd:anyType is used.

Where xsd: is "http://www.w3.org/2001/XMLSchema" namespace, soap-enc: is a "http://schemas.xmlsoap.org/soap/encoding/" namespace, tns: is a "target namespace" for a service.

WSDL Binding Styles

WSDL offers different transport mechanisms and styles. This affects the soap:binding and soap:body tags within the Binding section of WSDL. Different clients have different requirements as to what options really work. Therefore you can set the styles before you call any setClass or addFunction method on the AutoDiscover class.

  1. $autodiscover = new Zend_Soap_AutoDiscover();
  2. // Default is 'use' => 'encoded' and
  3. // 'encodingStyle' => 'http://schemas.xmlsoap.org/soap/encoding/'
  4. $autodiscover->setOperationBodyStyle(
  5.                     array('use' => 'literal',
  6.                           'namespace' => 'http://framework.zend.com')
  7.                 );
  8.
  9. // Default is 'style' => 'rpc' and
  10. // 'transport' => 'http://schemas.xmlsoap.org/soap/http'
  11. $autodiscover->setBindingStyle(
  12.                     array('style' => 'document',
  13.                           'transport' => 'http://framework.zend.com')
  14.                 );
  15. ...
  16. $autodiscover->addFunction('myfunc1');
  17. $autodiscover->handle();

[1] will be created with the class as detection algorithm for complex types. The first parameter of the AutoDiscover constructor takes any complex type strategy implementing or a string with the name of the class. For backwards compatibility with boolean variables are parsed exactly like in . See the types for more information.
WSDL Accessor
Zend_Soap
Zend Framework手册 中文版
Zend_Tag
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Soap
  • Zend_Soap_Server
  • Zend_Soap_Client
  • WSDL Accessor
  • AutoDiscovery


Zend_Tag - Zend Framework Manual

AutoDiscovery
Zend Framework Reference
Zend Framework手册 中文版
Introduction

Zend_Tag

Table of Contents
  • Introduction
  • Zend_Tag_Cloud
AutoDiscovery
Zend Framework Reference
Zend Framework手册 中文版
Introduction
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


Introduction - Zend Framework Manual

Zend_Tag
Zend_Tag
Zend Framework手册 中文版
Zend_Tag_Cloud

Introduction

Zend_Tag is a component suite which provides a facility to work with taggable Items. As its base, it provides two classes to work with Tags, Zend_Tag_Item and Zend_Tag_ItemList. Additionally, it comes with the interface Zend_Tag_Taggable, which allows you to use any of your models as a taggable item in conjunction with Zend_Tag.

Zend_Tag_Item is a basic taggable item implementation which comes with the essential functionality required to work with the Zend_Tag suite. A taggable item always consists of a title and a relative weight (e.g. number of occurrences). It also stores parameters which are used by the different sub-components of Zend_Tag.

To group multiple items together, Zend_Tag_ItemList exists as an array iterator and provides additional functionality to calculate absolute weight values based on the given relative weights of each item in it.

Example #1 Using Zend_Tag

This example illustrates how to create a list of tags and spread absolute weight values on them.

  1. // Create the item list
  2. $list = new Zend_Tag_ItemList();
  3.
  4. // Assign tags to it
  5. $list[] = new Zend_Tag_Item(array('title' => 'Code', 'weight' => 50));
  6. $list[] = new Zend_Tag_Item(array('title' => 'Zend Framework', 'weight' => 1));
  7. $list[] = new Zend_Tag_Item(array('title' => 'PHP', 'weight' => 5));
  8.
  9. // Spread absolute values on the items
  10. $list->spreadWeightValues(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
  11.
  12. // Output the items with their absolute values
  13. foreach ($list as $item) {
  14.     printf("%s: %d\n", $item->getTitle(), $item->getParam('weightValue'));
  15. }

This will output the three items Code, Zend Framework and PHP with the absolute values 10, 1 and 2.

Zend_Tag
Zend_Tag
Zend Framework手册 中文版
Zend_Tag_Cloud
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Tag
  • Introduction
  • Zend_Tag_Cloud


Zend_Tag_Cloud - Zend Framework Manual

Introduction
Zend_Tag
Zend Framework手册 中文版
Zend_Test

Zend_Tag_Cloud

Zend_Tag_Cloud is the rendering part of Zend_Tag. By default it comes with a set of HTML decorators, which allow you to create tag clouds for a website, but also supplies you with two abstract classes to create your own decorators, to create tag clouds in PDF documents for example.

You can instantiate and configure Zend_Tag_Cloud either programatically or completely via an array or an instance of Zend_Config. The available options are:

  • cloudDecorator: defines the decorator for the cloud. Can either be the name of the class which should be loaded by the pluginloader, an instance of Zend_Tag_Cloud_Decorator_Cloud or an array containing the string decorator and optionally an array options, which will be passed to the decorators constructor.

  • tagDecorator: defines the decorator for individual tags. This can either be the name of the class which should be loaded by the pluginloader, an instance of Zend_Tag_Cloud_Decorator_Tag or an array containing the string decorator and optionally an array options, which will be passed to the decorators constructor.

  • pluginLoader: a different plugin loader to use. Must be an instance of Zend_Loader_PluginLoader_Interface.

  • prefixPath: prefix paths to add to the plugin loader. Must be an array containing the keys prefix and path or multiple arrays containing the keys prefix and path. Invalid elements will be skipped.

  • itemList: a different item list to use. Must be an instance of Zend_Tag_ItemList.

  • tags: a list of tags to assign to the cloud. Each tag must either implement Zend_Tag_Taggable or be an array which can be used to instantiate Zend_Tag_Item.

Example #1 Using Zend_Tag_Cloud

This example illustrates a basic example of how to create a tag cloud, add multiple tags to it and finally render it.

  1. // Create the cloud and assign static tags to it
  2. $cloud = new Zend_Tag_Cloud(array(
  3.     'tags' => array(
  4.         array('title' => 'Code', 'weight' => 50,
  5.               'params' => array('url' => '/tag/code')),
  6.         array('title' => 'Zend Framework', 'weight' => 1,
  7.               'params' => array('url' => '/tag/zend-framework')),
  8.         array('title' => 'PHP', 'weight' => 5,
  9.               'params' => array('url' => '/tag/php')),
  10.     )
  11. ));
  12.
  13. // Render the cloud
  14. echo $cloud;

This will output the tag cloud with the three tags, spread with the default font-sizes.

Decorators

Zend_Tag_Cloud requires two types of decorators to be able to render a tag cloud. This includes a decorator which renders the single tags as well as a decorator which renders the surounding cloud. Zend_Tag_Cloud ships a default decorator set for formatting a tag cloud in HTML. This set will by default create a tag cloud as ul/li-list, spread with different font-sizes according to the weight values of the tags assigned to them.

HTML Tag decorator

The HTML tag decorator will by default render every tag in an anchor element, surounded by a li element. The anchor itself is fixed and cannot be changed, but the surounding element(s) can.

Note: URL parameter
 As the HTML tag decorator always surounds the tag title with an anchor, you should define an URL parameter for every tag used in it.

The tag decorator can either spread different font-sizes over the anchors or a defined list of classnames. When setting options for one of those possibilities, the corespondening one will automatically be enabled. The following configuration options are available:

  • fontSizeUnit: defines the font-size unit used for all font-sizes. The possible values are: em, ex, px, in, cm, mm, pt, pc and %.

  • minFontSize: the minimum font-size distributed through the tags (must be an integer).

  • maxFontSize: the maximum font-size distributed through the tags (must be an integer).

  • classList: an arry of classes distributed through the tags.

  • htmlTags: an array of HTML tags surounding the anchor. Each element can either be a string, which is used as element type then, or an array containing an attribute list for the element, defined as key/value pair. In this case, the array key is used as element type.

HTML Cloud decorator

The HTML cloud decorator will suround the HTML tags with an ul-element by default and add no separation. Like in the tag decorator, you can define multiple surounding HTML tags and additionally define a separator. The available options are:

  • separator: defines the separator which is placed between all tags.

  • htmlTags: an array of HTML tags surounding all tags. Each element can either be a string, which is used as element type then, or an array containing an attribute list for the element, defined as key/value pair. In this case, the array key is used as element type.

Introduction
Zend_Tag
Zend Framework手册 中文版
Zend_Test
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Tag
  • Introduction
  • Zend_Tag_Cloud


Zend_Test - Zend Framework Manual

Zend_Tag_Cloud
Zend Framework Reference
Zend Framework手册 中文版
简介

Zend_Test

Table of Contents
  • 简介
  • Zend_Test_PHPUnit
  • Zend_Test_PHPUnit_Db
Zend_Tag_Cloud
Zend Framework Reference
Zend Framework手册 中文版
简介
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


简介 - Zend Framework Manual

Zend_Test
Zend_Test
Zend Framework手册 中文版
Zend_Test_PHPUnit

简介

Zend_Test 提供了对 Zend Framework 应用进行单元测试的便利工具。 现在，已经可以对 Zend Framework MVC 应用方便的进行测试了。

Zend_Test
Zend_Test
Zend Framework手册 中文版
Zend_Test_PHPUnit
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Test
  • 简介
  • Zend_Test_PHPUnit
  • Zend_Test_PHPUnit_Db


Zend_Test_PHPUnit - Zend Framework Manual

简介
Zend_Test
Zend Framework手册 中文版
Zend_Test_PHPUnit_Db

Zend_Test_PHPUnit

Zend_Test_PHPUnit provides a TestCase for MVC applications that contains assertions for testing against a variety of responsibilities. Probably the easiest way to understand what it can do is to see an example.

Example #1 Application Login TestCase example

The following is a simple test case for a UserController to verify several things:

  • The login form should be displayed to non-authenticated users.

  • When a user logs in, they should be redirected to their profile page, and that profile page should show relevant information.

This particular example assumes a few things. First, we're moving most of our bootstrapping to a plugin. This simplifies setup of the test case as it allows us to specify our environment succinctly, and also allows us to bootstrap the application in a single line. Also, our particular example is assuming that autoloading is setup so we do not need to worry about requiring the appropriate classes (such as the correct controller, plugin, etc).

  1. class UserControllerTest extends Zend_Test_PHPUnit_ControllerTestCase
  2. {
  3.     public function setUp()
  4.     {
  5.         $this->bootstrap = array($this, 'appBootstrap');
  6.         parent::setUp();
  7.     }
  8.
  9.     public function appBootstrap()
  10.     {
  11.         $this->frontController
  12.              ->registerPlugin(new Bugapp_Plugin_Initialize('development'));
  13.     }
  14.
  15.     public function testCallWithoutActionShouldPullFromIndexAction()
  16.     {
  17.         $this->dispatch('/user');
  18.         $this->assertController('user');
  19.         $this->assertAction('index');
  20.     }
  21.
  22.     public function testIndexActionShouldContainLoginForm()
  23.     {
  24.         $this->dispatch('/user');
  25.         $this->assertAction('index');
  26.         $this->assertQueryCount('form#loginForm', 1);
  27.     }
  28.
  29.     public function testValidLoginShouldGoToProfilePage()
  30.     {
  31.         $this->request->setMethod('POST')
  32.               ->setPost(array(
  33.                   'username' => 'foobar',
  34.                   'password' => 'foobar'
  35.               ));
  36.         $this->dispatch('/user/login');
  37.         $this->assertRedirectTo('/user/view');
  38.
  39.         $this->resetRequest()
  40.              ->resetResponse();
  41.
  42.         $this->request->setMethod('GET')
  43.              ->setPost(array());
  44.         $this->dispatch('/user/view');
  45.         $this->assertRoute('default');
  46.         $this->assertModule('default');
  47.         $this->assertController('user');
  48.         $this->assertAction('view');
  49.         $this->assertNotRedirect();
  50.         $this->assertQuery('dl');
  51.         $this->assertQueryContentContains('h2', 'User: foobar');
  52.     }
  53. }

This example could be written somewhat simpler -- not all the assertions shown are necessary, and are provided for illustration purposes only. Hopefully, it shows how simple it can be to test your applications.

Bootstrapping your TestCase

As noted in the Login example, all MVC test cases should extend Zend_Test_PHPUnit_ControllerTestCase. This class in turn extends PHPUnit_Framework_TestCase, and gives you all the structure and assertions you'd expect from PHPUnit -- as well as some scaffolding and assertions specific to Zend Framework's MVC implementation.

In order to test your MVC application, you will need to bootstrap it. There are several ways to do this, all of which hinge on the public $bootstrap property.

First, and probably most straight-forward, simply create a Zend_Application instance as you would in your index.php, and assign it to the $bootstrap property. Typically, you will do this in your setUp() method; you will need to call parent::setUp() when done:

  1. class UserControllerTest extends Zend_Test_PHPUnit_ControllerTestCase
  2. {
  3.     public function setUp()
  4.     {
  5.         // Assign and instantiate in one step:
  6.         $this->bootstrap = new Zend_Application(
  7.             'testing',
  8.             APPLICATION_PATH . '/configs/application.ini'
  9.         );
  10.         parent::setUp();
  11.     }
  12. }

Second, you can set this property to point to a file. If you do this, the file should not dispatch the front controller, but merely setup the front controller and any application specific needs.

  1. class UserControllerTest extends Zend_Test_PHPUnit_ControllerTestCase
  2. {
  3.     public $bootstrap = '/path/to/bootstrap/file.php'
  4.
  5.     // ...
  6. }

Third, you can provide a PHP callback to execute in order to bootstrap your application. This method is seen in the Login example. If the callback is a function or static method, this could be set at the class level:

  1. class UserControllerTest extends Zend_Test_PHPUnit_ControllerTestCase
  2. {
  3.     public $bootstrap = array('App', 'bootstrap');
  4.
  5.     // ...
  6. }

In cases where an object instance is necessary, we recommend performing this in your setUp() method:

  1. class UserControllerTest extends Zend_Test_PHPUnit_ControllerTestCase
  2. {
  3.     public function setUp()
  4.     {
  5.         // Use the 'start' method of a Bootstrap object instance:
  6.         $bootstrap = new Bootstrap('test');
  7.         $this->bootstrap = array($bootstrap, 'start');
  8.         parent::setUp();
  9.     }
  10. }

Note the call to parent::setUp(); this is necessary, as the setUp() method of Zend_Test_PHPUnit_ControllerTestCase will perform the remainder of the bootstrapping process (which includes calling the callback).

During normal operation, the setUp() method will bootstrap the application. This process first will include cleaning up the environment to a clean request state, resetting any plugins and helpers, resetting the front controller instance, and creating new request and response objects. Once this is done, it will then either include() the file specified in $bootstrap, or call the callback specified.

Bootstrapping should be as close as possible to how the application will be bootstrapped. However, there are several caveats:

  • Do not provide alternate implementations of the Request and Response objects; they will not be used. Zend_Test_PHPUnit_ControllerTestCase uses custom request and response objects, Zend_Controller_Request_HttpTestCase and Zend_Controller_Response_HttpTestCase, respectively. These objects provide methods for setting up the request environment in targeted ways, and pulling response artifacts in specific ways.

  • Do not expect to test server specifics. In other words, the tests are not a guarantee that the code will run on a specific server configuration, but merely that the application should run as expected should the router be able to route the given request. To this end, do not set server-specific headers in the request object.

Once the application is bootstrapped, you can then start creating your tests.

Testing your Controllers and MVC Applications

Once you have your bootstrap in place, you can begin testing. Testing is basically as you would expect in an PHPUnit test suite, with a few minor differences.

First, you will need to dispatch a URL to test, using the dispatch() method of the TestCase:

  1. class IndexControllerTest extends Zend_Test_PHPUnit_ControllerTestCase
  2. {
  3.     // ...
  4.
  5.     public function testHomePage()
  6.     {
  7.         $this->dispatch('/');
  8.         // ...
  9.     }
  10. }

There will be times, however, that you need to provide extra information -- GET and POST variables, COOKIE information, etc. You can populate the request with that information:

  1. class FooControllerTest extends Zend_Test_PHPUnit_ControllerTestCase
  2. {
  3.     // ...
  4.
  5.     public function testBarActionShouldReceiveAllParameters()
  6.     {
  7.         // Set GET variables:
  8.         $this->request->setQuery(array(
  9.             'foo' => 'bar',
  10.             'bar' => 'baz',
  11.         ));
  12.
  13.         // Set POST variables:
  14.         $this->request->setPost(array(
  15.             'baz'  => 'bat',
  16.             'lame' => 'bogus',
  17.         ));
  18.
  19.         // Set a cookie value:
  20.         $this->request->setCookie('user', 'matthew');
  21.         // or many:
  22.         $this->request->setCookies(array(
  23.             'timestamp' => time(),
  24.             'host'      => 'foobar',
  25.         ));
  26.
  27.         // Set headers, even:
  28.         $this->request->setHeader('X-Requested-With', 'XmlHttpRequest');
  29.
  30.         // Set the request method:
  31.         $this->request->setMethod('POST');
  32.
  33.         // Dispatch:
  34.         $this->dispatch('/foo/bar');
  35.
  36.         // ...
  37.     }
  38. }

Now that the request is made, it's time to start making assertions against it.

Controller Tests and the Redirector Action Helper

Important

The redirect action helper issues an exit() statement when using the method gotoAndExit() and will then obviously also stops a test running for this method. For testability of your application dont use that method on the redirector!

Due to its nature the redirector action helper plugin issues a redirect and exists after this. Because you cannot test parts of an application that issue exit calls Zend_Test_PHPUnit_ControllerTestCase automatically disables the exit part of the redirector which can cause different behaviours in tests and the real application. To make sure redirect work correctly you should it them in the following way:

  1. class MyController extends Zend_Controller_Action
  2. {
  3.     public function indexAction()
  4.     {
  5.         if($someCondition == true) {
  6.             return $this->_redirect(...);
  7.         } else if($anotherCondition == true) {
  8.             $this->_redirector->gotoSimple("foo");
  9.             return;
  10.         }
  11.
  12.         // do some stuff here
  13.     }
  14. }
Important

Depending on your application this is not enough as additional action, preDispatch() or postDispatch() logic might be executed. This cannot be handled in a good way with Zend Test currently.

Assertions

Assertions are at the heart of Unit Testing; you use them to verify that the results are what you expect. To this end, Zend_Test_PHPUnit_ControllerTestCase provides a number of assertions to make testing your MVC apps and controllers simpler.

CSS Selector Assertions

CSS selectors are an easy way to verify that certain artifacts are present in the response content. They also make it trivial to ensure that items necessary for Javascript UIs and/or AJAX integration will be present; most JS toolkits provide some mechanism for pulling DOM elements based on CSS selectors, so the syntax would be the same.

This functionality is provided via Zend_Dom_Query, and integrated into a set of 'Query' assertions. Each of these assertions takes as their first argument a CSS selector, with optionally additional arguments and/or an error message, based on the assertion type. You can find the rules for writing the CSS selectors in the Zend_Dom_Query theory of operation chapter. Query assertions include:

  • assertQuery($path, $message = ''): assert that one or more DOM elements matching the given CSS selector are present. If a $message is present, it will be prepended to any failed assertion message.

  • assertQueryContentContains($path, $match, $message = ''): assert that one or more DOM elements matching the given CSS selector are present, and that at least one contains the content provided in $match. If a $message is present, it will be prepended to any failed assertion message.

  • assertQueryContentRegex($path, $pattern, $message = ''): assert that one or more DOM elements matching the given CSS selector are present, and that at least one matches the regular expression provided in $pattern. If a $message is present, it will be prepended to any failed assertion message.

  • assertQueryCount($path, $count, $message = ''): assert that there are exactly $count DOM elements matching the given CSS selector present. If a $message is present, it will be prepended to any failed assertion message.

  • assertQueryCountMin($path, $count, $message = ''): assert that there are at least $count DOM elements matching the given CSS selector present. If a $message is present, it will be prepended to any failed assertion message. Note: specifying a value of 1 for $count is the same as simply using assertQuery().

  • assertQueryCountMax($path, $count, $message = ''): assert that there are no more than $count DOM elements matching the given CSS selector present. If a $message is present, it will be prepended to any failed assertion message. Note: specifying a value of 1 for $count is the same as simply using assertQuery().

Additionally, each of the above has a 'Not' variant that provides a negative assertion: assertNotQuery(), assertNotQueryContentContains(), assertNotQueryContentRegex(), and assertNotQueryCount(). (Note that the min and max counts do not have these variants, for what should be obvious reasons.)

XPath Assertions

Some developers are more familiar with XPath than with CSS selectors, and thus XPath variants of all the Query assertions are also provided. These are:

  • assertXpath($path, $message = '')

  • assertNotXpath($path, $message = '')

  • assertXpathContentContains($path, $match, $message = '')

  • assertNotXpathContentContains($path, $match, $message = '')

  • assertXpathContentRegex($path, $pattern, $message = '')

  • assertNotXpathContentRegex($path, $pattern, $message = '')

  • assertXpathCount($path, $count, $message = '')

  • assertNotXpathCount($path, $count, $message = '')

  • assertXpathCountMin($path, $count, $message = '')

  • assertNotXpathCountMax($path, $count, $message = '')

Redirect Assertions

Often an action will redirect. Instead of following the redirect, Zend_Test_PHPUnit_ControllerTestCase allows you to test for redirects with a handful of assertions.

  • assertRedirect($message = ''): assert simply that a redirect has occurred.

  • assertNotRedirect($message = ''): assert that no redirect has occurred.

  • assertRedirectTo($url, $message = ''): assert that a redirect has occurred, and that the value of the Location header is the $url provided.

  • assertNotRedirectTo($url, $message = ''): assert that a redirect has either NOT occurred, or that the value of the Location header is NOT the $url provided.

  • assertRedirectRegex($pattern, $message = ''): assert that a redirect has occurred, and that the value of the Location header matches the regular expression provided by $pattern.

  • assertNotRedirectRegex($pattern, $message = ''): assert that a redirect has either NOT occurred, or that the value of the Location header does NOT match the regular expression provided by $pattern.

Response Header Assertions

In addition to checking for redirect headers, you will often need to check for specific HTTP response codes and headers -- for instance, to determine whether an action results in a 404 or 500 response, or to ensure that JSON responses contain the appropriate Content-Type header. The following assertions are available.

  • assertResponseCode($code, $message = ''): assert that the response resulted in the given HTTP response code.

  • assertHeader($header, $message = ''): assert that the response contains the given header.

  • assertHeaderContains($header, $match, $message = ''): assert that the response contains the given header and that its content contains the given string.

  • assertHeaderRegex($header, $pattern, $message = ''): assert that the response contains the given header and that its content matches the given regex.

Additionally, each of the above assertions have a 'Not' variant for negative assertions.

Request Assertions

It's often useful to assert against the last run action, controller, and module; additionally, you may want to assert against the route that was matched. The following assertions can help you in this regard:

  • assertModule($module, $message = ''): Assert that the given module was used in the last dispatched action.

  • assertController($controller, $message = ''): Assert that the given controller was selected in the last dispatched action.

  • assertAction($action, $message = ''): Assert that the given action was last dispatched.

  • assertRoute($route, $message = ''): Assert that the given named route was matched by the router.

Each also has a 'Not' variant for negative assertions.

Examples

Knowing how to setup your testing infrastructure and how to make assertions is only half the battle; now it's time to start looking at some actual testing scenarios to see how you can leverage them.

Example #2 Testing a UserController

Let's consider a standard task for a website: authenticating and registering users. In our example, we'll define a UserController for handling this, and have the following requirements:

  • If a user is not authenticated, they will always be redirected to the login page of the controller, regardless of the action specified.

  • The login form page will show both the login form and the registration form.

  • Providing invalid credentials should result in returning to the login form.

  • Valid credentials should result in redirecting to the user profile page.

  • The profile page should be customized to contain the user's username.

  • Authenticated users who visit the login page should be redirected to their profile page.

  • On logout, a user should be redirected to the login page.

  • With invalid data, registration should fail.

We could, and should define further tests, but these will do for now.

For our application, we will define a plugin, 'Initialize', that runs at routeStartup(). This allows us to encapsulate our bootstrap in an OOP interface, which also provides an easy way to provide a callback. Let's look at the basics of this class first:

  1. class Bugapp_Plugin_Initialize extends Zend_Controller_Plugin_Abstract
  2. {
  3.     /**
  4.      * @var Zend_Config
  5.      */
  6.     protected static $_config;
  7.
  8.     /**
  9.      * @var string Current environment
  10.      */
  11.     protected $_env;
  12.
  13.     /**
  14.      * @var Zend_Controller_Front
  15.      */
  16.     protected $_front;
  17.
  18.     /**
  19.      * @var string Path to application root
  20.      */
  21.     protected $_root;
  22.
  23.     /**
  24.      * Constructor
  25.      *
  26.      * Initialize environment, root path, and configuration.
  27.      *
  28.      * @param  string $env
  29.      * @param  string|null $root
  30.      * @return void
  31.      */
  32.     public function __construct($env, $root = null)
  33.     {
  34.         $this->_setEnv($env);
  35.         if (null === $root) {
  36.             $root = realpath(dirname(__FILE__) . '/../../../');
  37.         }
  38.         $this->_root = $root;
  39.
  40.         $this->initPhpConfig();
  41.
  42.         $this->_front = Zend_Controller_Front::getInstance();
  43.     }
  44.
  45.     /**
  46.      * Route startup
  47.      *
  48.      * @return void
  49.      */
  50.     public function routeStartup(Zend_Controller_Request_Abstract $request)
  51.     {
  52.         $this->initDb();
  53.         $this->initHelpers();
  54.         $this->initView();
  55.         $this->initPlugins();
  56.         $this->initRoutes();
  57.         $this->initControllers();
  58.     }
  59.
  60.     // definition of methods would follow...
  61. }

This allows us to create a bootstrap callback like the following:

  1. class UserControllerTest extends Zend_Test_PHPUnit_ControllerTestCase
  2. {
  3.     public function appBootstrap()
  4.     {
  5.         $controller = $this->getFrontController();
  6.         $controller->registerPlugin(
  7.             new Bugapp_Plugin_Initialize('development')
  8.         );
  9.     }
  10.
  11.     public function setUp()
  12.     {
  13.         $this->bootstrap = array($this, 'appBootstrap');
  14.         parent::setUp();
  15.     }
  16.
  17.     // ...
  18. }

Once we have that in place, we can write our tests. However, what about those tests that require a user is logged in? The easy solution is to use our application logic to do so... and fudge a little by using the resetRequest() and resetResponse() methods, which will allow us to dispatch another request.

  1. class UserControllerTest extends Zend_Test_PHPUnit_ControllerTestCase
  2. {
  3.     // ...
  4.
  5.     public function loginUser($user, $password)
  6.     {
  7.         $this->request->setMethod('POST')
  8.                       ->setPost(array(
  9.                           'username' => $user,
  10.                           'password' => $password,
  11.                       ));
  12.         $this->dispatch('/user/login');
  13.         $this->assertRedirectTo('/user/view');
  14.
  15.         $this->resetRequest()
  16.              ->resetResponse();
  17.
  18.         $this->request->setPost(array());
  19.
  20.         // ...
  21.     }
  22.
  23.     // ...
  24. }

Now let's write tests:

  1. class UserControllerTest extends Zend_Test_PHPUnit_ControllerTestCase
  2. {
  3.     // ...
  4.
  5.     public function testCallWithoutActionShouldPullFromIndexAction()
  6.     {
  7.         $this->dispatch('/user');
  8.         $this->assertController('user');
  9.         $this->assertAction('index');
  10.     }
  11.
  12.     public function testLoginFormShouldContainLoginAndRegistrationForms()
  13.     {
  14.         $this->dispatch('/user');
  15.         $this->assertQueryCount('form', 2);
  16.     }
  17.
  18.     public function testInvalidCredentialsShouldResultInRedisplayOfLoginForm()
  19.     {
  20.         $request = $this->getRequest();
  21.         $request->setMethod('POST')
  22.                 ->setPost(array(
  23.                     'username' => 'bogus',
  24.                     'password' => 'reallyReallyBogus',
  25.                 ));
  26.         $this->dispatch('/user/login');
  27.         $this->assertNotRedirect();
  28.         $this->assertQuery('form');
  29.     }
  30.
  31.     public function testValidLoginShouldRedirectToProfilePage()
  32.     {
  33.         $this->loginUser('foobar', 'foobar');
  34.     }
  35.
  36.     public function testAuthenticatedUserShouldHaveCustomizedProfilePage()
  37.     {
  38.         $this->loginUser('foobar', 'foobar');
  39.         $this->request->setMethod('GET');
  40.         $this->dispatch('/user/view');
  41.         $this->assertNotRedirect();
  42.         $this->assertQueryContentContains('h2', 'foobar');
  43.     }
  44.
  45.     public function
  46.         testAuthenticatedUsersShouldBeRedirectedToProfileWhenVisitingLogin()
  47.     {
  48.         $this->loginUser('foobar', 'foobar');
  49.         $this->request->setMethod('GET');
  50.         $this->dispatch('/user');
  51.         $this->assertRedirectTo('/user/view');
  52.     }
  53.
  54.     public function testUserShouldRedirectToLoginPageOnLogout()
  55.     {
  56.         $this->loginUser('foobar', 'foobar');
  57.         $this->request->setMethod('GET');
  58.         $this->dispatch('/user/logout');
  59.         $this->assertRedirectTo('/user');
  60.     }
  61.
  62.     public function testRegistrationShouldFailWithInvalidData()
  63.     {
  64.         $data = array(
  65.             'username' => 'This will not work',
  66.             'email'    => 'this is an invalid email',
  67.             'password' => 'Th1s!s!nv@l1d',
  68.             'passwordVerification' => 'wrong!',
  69.         );
  70.         $request = $this->getRequest();
  71.         $request->setMethod('POST')
  72.                 ->setPost($data);
  73.         $this->dispatch('/user/register');
  74.         $this->assertNotRedirect();
  75.         $this->assertQuery('form .errors');
  76.     }
  77. }

Notice that these are terse, and, for the most part, don't look for actual content. Instead, they look for artifacts within the response -- response codes and headers, and DOM nodes. This allows you to verify that the structure is as expected -- preventing your tests from choking every time new content is added to the site.

Also notice that we use the structure of the document in our tests. For instance, in the final test, we look for a form that has a node with the class of "errors"; this allows us to test merely for the presence of form validation errors, and not worry about what specific errors might have been thrown.

This application may utilize a database. If so, you will probably need some scaffolding to ensure that the database is in a pristine, testable configuration at the beginning of each test. PHPUnit already provides functionality for doing so; » read about it in the PHPUnit documentation. We recommend using a separate database for testing versus production, and in particular recommend using either a SQLite file or in-memory database, as both options perform very well, do not require a separate server, and can utilize most SQL syntax.

简介
Zend_Test
Zend Framework手册 中文版
Zend_Test_PHPUnit_Db
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Test
  • 简介
  • Zend_Test_PHPUnit
  • Zend_Test_PHPUnit_Db


Zend_Test_PHPUnit_Db - Zend Framework Manual

Zend_Test_PHPUnit
Zend_Test
Zend Framework手册 中文版
Zend_Text

Zend_Test_PHPUnit_Db

Coupling of data-access and the domain model often requires the use of a database for testing purposes. But the database is persistent across different tests which leads to test results that can affect each other. Furthermore setting up the database to be able to run a test is quite some work. PHPUnit's Database extension simplifies testing with a database by offering a very simple mechanism to set up and teardown the database between different tests. This component extends the PHPUnit Database extension with Zend Framework specific code, such that writing database tests against a Zend Framework application is simplified.

Database Testing can be explained with two conceptual entities, DataSets and DataTables. Internally the PHPUnit Database extension can build up an object structure of a database, its tables and containing rows from configuration files or the real database content. This abstract object graph can then be compared using assertions. A common use-case in database testing is setting up some tables with seed data, then performing some operations, and finally asserting that the operated on database-state is equal to some predefined expected state. Zend_Test_PHPUnit_Db simplifies this task by allowing to generate DataSets and DataTables from existing Zend_Db_Table_Abstract or Zend_Db_Table_Rowset_Abstract instances.

Furthermore this component allows to integrate any Zend_Db_Adapter_Abstract for testing whereas the original extension only works with PDO. A Test Adapter implementation for Zend_Db_Adapter_Abstract is also included in this component. It allows to instantiate a Db Adapter that requires no database at all and acts as an SQL and result stack which is used by the API methods.

Quickstart

Setup a Database TestCase

We are now writting some database tests for the Bug Database example in the Zend_Db_Table documentation. First we begin to test that inserting a new bug is actually saved in the database correctly. First we have to setup a test-class that extends Zend_Test_PHPUnit_DatabaseTestCase. This class extends the PHPUnit Database Extension, which in turn extends the basic PHPUnit_Framework_TestCase. A database testcase contains two abstract methods that have to be implemented, one for the database connection and one for the initial dataset that should be used as seed or fixture.

Note: You should be familiar with the PHPUnit Database extension to follow this quickstart easily. Although all the concepts are explained in this documentation it may be helpful to read the PHPUnit documentation first.

  1. class BugsTest extends Zend_Test_PHPUnit_DatabaseTestCase
  2. {
  3.     private $_connectionMock;
  4.
  5.     /**
  6.      * Returns the test database connection.
  7.      *
  8.      * @return PHPUnit_Extensions_Database_DB_IDatabaseConnection
  9.      */
  10.     protected function getConnection()
  11.     {
  12.         if($this->_connectionMock == null) {
  13.             $connection = Zend_Db::factory(...);
  14.             $this->_connectionMock = $this->createZendDbConnection(
  15.                 $connection, 'zfunittests'
  16.             );
  17.             Zend_Db_Table_Abstract::setDefaultAdapter($connection);
  18.         }
  19.         return $this->_connectionMock;
  20.     }
  21.
  22.     /**
  23.      * @return PHPUnit_Extensions_Database_DataSet_IDataSet
  24.      */
  25.     protected function getDataSet()
  26.     {
  27.         return $this->createFlatXmlDataSet(
  28.             dirname(__FILE__) . '/_files/bugsSeed.xml'
  29.         );
  30.     }
  31. }

Here we create the database connection and seed some data into the database. Some important details should be noted on this code:

  • You cannot directly return a Zend_Db_Adapter_Abstract from the getConnection() method, but a PHPUnit specific wrapper which is generated with the createZendDbConnection() method.

  • The database schema (tables and database) is not re-created on every testrun. The database and tables have to be created manually before running the tests.

  • Database tests by default truncate the data during setUp() and then insert the seed data which is returned from the getDataSet() method.

  • DataSets have to implement the interface PHPUnit_Extensions_Database_DataSet_IDataSet. There is a wide range of XML and YAML configuration file types included in PHPUnit which allows to specifiy how the tables and datasets should look like and you should look into the PHPUnit documentation to get the latest information on these dataset specifications.

Specify a seed dataset

In the previous setup for the database testcase we have specified a seed file for the database fixture. We now create this file specified in the Flat XML format:

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <dataset>
  3.     <zfbugs bug_id="1" bug_description="system needs electricity to run"
  4.         bug_status="NEW" created_on="2007-04-01 00:00:00"
  5.         updated_on="2007-04-01 00:00:00" reported_by="goofy"
  6.         assigned_to="mmouse" verified_by="dduck" />
  7.     <zfbugs bug_id="2" bug_description="Implement Do What I Mean function"
  8.         bug_status="VERIFIED" created_on="2007-04-02 00:00:00"
  9.         updated_on="2007-04-02 00:00:00" reported_by="goofy"
  10.         assigned_to="mmouse" verified_by="dduck" />
  11.     <zfbugs bug_id="3" bug_description="Where are my keys?" bug_status="FIXED"
  12.         created_on="2007-04-03 00:00:00" updated_on="2007-04-03 00:00:00"
  13.         reported_by="dduck" assigned_to="mmouse" verified_by="dduck" />
  14.     <zfbugs bug_id="4" bug_description="Bug no product" bug_status="INCOMPLETE"
  15.         created_on="2007-04-04 00:00:00" updated_on="2007-04-04 00:00:00"
  16.         reported_by="mmouse" assigned_to="goofy" verified_by="dduck" />
  17. </dataset>

We will work with this four entries in the database table "zfbugs" in the next examples. The required MySQL schema for this example is:

  1. CREATE TABLE IF NOT EXISTS `zfbugs` (
  2.     `bug_id` int(11) NOT NULL AUTO_INCREMENT,
  3.     `bug_description` varchar(100) DEFAULT NULL,
  4.     `bug_status` varchar(20) DEFAULT NULL,
  5.     `created_on` datetime DEFAULT NULL,
  6.     `updated_on` datetime DEFAULT NULL,
  7.     `reported_by` varchar(100) DEFAULT NULL,
  8.     `assigned_to` varchar(100) DEFAULT NULL,
  9.     `verified_by` varchar(100) DEFAULT NULL,
  10. PRIMARY KEY  (`bug_id`)
  11. ) ENGINE=InnoDB AUTO_INCREMENT=1 ;

A few initial database tests

Now that we have implemented the two required abstract methods of the Zend_Test_PHPUnit_DatabaseTestCase and specified the seed database content, which will be re-created for each new test, we can go about to make our first assertion. This will be a test to insert a new bug.

  1. class BugsTest extends Zend_Test_PHPUnit_DatabaseTestCase
  2. {
  3.     public function testBugInsertedIntoDatabase()
  4.     {
  5.         $bugsTable = new Bugs();
  6.
  7.         $data = array(
  8.             'created_on'      => '2007-03-22 00:00:00',
  9.             'updated_on'      => '2007-03-22 00:00:00',
  10.             'bug_description' => 'Something wrong',
  11.             'bug_status'      => 'NEW',
  12.             'reported_by'     => 'garfield',
  13.             'verified_by'     => 'garfield',
  14.             'assigned_to'     => 'mmouse',
  15.         );
  16.
  17.         $bugsTable->insert($data);
  18.
  19.         $ds = new Zend_Test_PHPUnit_Db_DataSet_QueryDataSet(
  20.             $this->getConnection()
  21.         );
  22.         $ds->addTable('zfbugs', 'SELECT * FROM zfbugs');
  23.
  24.         $this->assertDataSetsEqual(
  25.             $this->createFlatXmlDataSet(dirname(__FILE__)
  26.                                       . "/_files/bugsInsertIntoAssertion.xml"),
  27.             $ds
  28.         );
  29.     }
  30. }

Now up to the $bugsTable->insert($data); everything looks familiar. The lines after that contain the assertion methodname. We want to verify that after inserting the new bug the database has been updated correctly with the given data. For this we create a Zend_Test_PHPUnit_Db_DataSet_QueryDataSet instance and give it a database connection. We will then tell this dataset that it contains a table "zfbugs" which is given by an SQL statement. This current/actual state of the database is compared to the expected database state which is contained in another XML file "bugsInsertIntoAssertions.xml". This XML file is a slight deviation from the one given above and contains another row with the expected data:

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <dataset>
  3.     <!-- previous 4 rows -->
  4.     <zfbugs bug_id="5" bug_description="Something wrong" bug_status="NEW"
  5.         created_on="2007-03-22 00:00:00" updated_on="2007-03-22 00:00:00"
  6.         reported_by="garfield" assigned_to="mmouse" verified_by="garfield" />
  7. </dataset>

There are other ways to assert that the current database state equals an expected state. The "Bugs" table in the example already nows a lot about its inner state, so why not use this to our advantage? The next example will assert that deleting from the database is possible:

  1. class BugsTest extends Zend_Test_PHPUnit_DatabaseTestCase
  2. {
  3.     public function testBugDelete()
  4.     {
  5.         $bugsTable = new Bugs();
  6.
  7.         $bugsTable->delete(
  8.             $bugsTable->getAdapter()->quoteInto("bug_id = ?", 4)
  9.         );
  10.
  11.         $ds = new Zend_Test_PHPUnit_Db_DataSet_DbTableDataSet();
  12.         $ds->addTable($bugsTable);
  13.
  14.         $this->assertDataSetsEqual(
  15.             $this->createFlatXmlDataSet(dirname(__FILE__)
  16.                                       . "/_files/bugsDeleteAssertion.xml"),
  17.             $ds
  18.         );
  19.     }
  20. }

We have created a Zend_Test_PHPUnit_Db_DataSet_DbTableDataSet dataset here, which takes any Zend_Db_Table_Abstract instance and adds it to the dataset with its table name, in this example "zfbugs". You could add several tables more if you wanted using the method addTable() if you want to check for expected database state in more than one table.

Here we only have one table and check against an expected database state in "bugsDeleteAssertion.xml" which is the original seed dataset without the row with id 4.

Since we have only checked that two specific tables (not datasets) are equal in the previous examples we should also look at how to assert that two tables are equal. Therefore we will add another test to our TestCase which verifies updating behaviour of a dataset.

  1. class BugsTest extends Zend_Test_PHPUnit_DatabaseTestCase
  2. {
  3.     public function testBugUpdate()
  4.     {
  5.         $bugsTable = new Bugs();
  6.
  7.         $data = array(
  8.             'updated_on'      => '2007-05-23',
  9.             'bug_status'      => 'FIXED'
  10.         );
  11.
  12.         $where = $bugsTable->getAdapter()->quoteInto('bug_id = ?', 1);
  13.
  14.         $bugsTable->update($data, $where);
  15.
  16.         $rowset = $bugsTable->fetchAll();
  17.
  18.         $ds        = new Zend_Test_PHPUnit_Db_DataSet_DbRowset($rowset);
  19.         $assertion = $this->createFlatXmlDataSet(
  20.             dirname(__FILE__) . '/_files/bugsUpdateAssertion.xml'
  21.         );
  22.         $expectedRowsets = $assertion->getTable('zfbugs');
  23.
  24.         $this->assertTablesEqual(
  25.             $expectedRowsets, $ds
  26.         );
  27.     }
  28. }

Here we create the current database state from a Zend_Db_Table_Rowset_Abstract instance in conjunction with the Zend_Test_PHPUnit_Db_DataSet_DbRowset($rowset) instance which creates an internal data-representation of the rowset. This can again be compared against another data-table by using the $this->assertTablesEqual() assertion.

Usage, API and Extensions Points

The Quickstart already gave a good introduction on how database testing can be done using PHPUnit and the Zend Framework. This section gives an overview over the API that the Zend_Test_PHPUnit_Db component comes with and how it works internally.

Note: Some Remarks on Database Testing
 Just as the Controller TestCase is testing an application at an integration level, the Database TestCase is an integration testing method. Its using several different application layers for testing purposes and therefore should be consumed with caution.
It should be noted that testing domain and business logic with integration tests such as Zend Framework's Controller and Database TestCases is a bad practice. The purpose of an Integration test is to check that several parts of an application work smoothly when wired together. These integration tests do not replace the need for a set of unit tests that test the domain and business logic at a much smaller level, the isolated class.

The Zend_Test_PHPUnit_DatabaseTestCase class

The Zend_Test_PHPUnit_DatabaseTestCase class derives from the PHPUnit_Extensions_Database_TestCase which allows to setup tests with a fresh database fixture on each run easily. The Zend implementation offers some additional convenience features over the PHPUnit Database extension when it comes to using Zend_Db resources inside your tests. The workflow of a database test-case can be described as follows.

  1. For each test PHPUnit creates a new instance of the TestCase and calls the setUp() method.

  2. The Database TestCase creates an instance of a Database Tester which handles the setting up and tearing down of the database.

  3. The database tester collects the information on the database connection and initial dataset from getConnection() and getDataSet() which are both abstract methods and have to be implemented by any Database Testcase.

  4. By default the database tester truncates the tables specified in the given dataset, and then inserts the data given as initial fixture.

  5. When the database tester has finished setting up the database, PHPUnit runs the test.

  6. After running the test, tearDown() is called. Because the database is wiped in setUp() before inserting the required initial fixture, no actions are executed by the database tester at this stage.

Note: The Database TestCase expects the database schema and tables to be setup correctly to run the tests. There is no mechanism to create and tear down database tables.

The Zend_Test_PHPUnit_DatabaseTestCase class has some convenience functions that can help writing tests that interact with the database and the database testing extension.

The next table lists only the new methods compared to the PHPUnit_Extensions_Database_TestCase, whose » API is documented in the PHPUnit Documentation.

Zend_Test_PHPUnit_DatabaseTestCase API Methods
Method | Description
createZendDbConnection(Zend_Db_Adapter_Abstract $connection, $schema) | Create a PHPUnit Database Extension compatible Connection instance from a Zend_Db_Adapter_Abstract instance. This method should be used in for testcase setup when implementing the abstract getConnection() method of the database testcase.
getAdapter() | Convenience method to access the underlying Zend_Db_Adapter_Abstract instance which is nested inside the PHPUnit database connection created with getConnection().
createDbRowset(Zend_Db_Table_Rowset_Abstract $rowset, $tableName = null) | Create a DataTable Object that is filled with the data from a given Zend_Db_Table_Rowset_Abstract instance. The table the rowset is connected to is chosen when $tableName is NULL.
createDbTable(Zend_Db_Table_Abstract $table, $where = null, $order = null, $count = null, $offset = null) | Create a DataTable object that represents the data contained in a Zend_Db_Table_Abstract instance. For retrieving the data fetchAll() is used, where the optional parameters can be used to restrict the data table to a certain subset.
createDbTableDataSet(array $tables=array()) | Create a DataSet containing the given $tables, an array of Zend_Db_Table_Abstract instances.

Integrating Database Testing with the ControllerTestCase

Because PHP does not support multiple inheritance it is not possible to use the Controller and Database testcases in conjunction. However you can use the Zend_Test_PHPUnit_Db_SimpleTester database tester in your controller test-case to setup a database enviroment fixture for each new controller test. The Database TestCase in general is only a set of convenience functions which can also be accessed and used without the test case.

Example #1 Database integration example

This example extends the User Controller Test from the Zend_Test_PHPUnit_ControllerTestCase documentation to include a database setup.

  1. class UserControllerTest extends Zend_Test_PHPUnit_ControllerTestCase
  2. {
  3.     public function setUp()
  4.     {
  5.         $this->setupDatabase();
  6.         $this->bootstrap = array($this, 'appBootstrap');
  7.         parent::setUp();
  8.     }
  9.
  10.     public function setupDatabase()
  11.     {
  12.         $db = Zend_Db::factory(...);
  13.         $connection = new Zend_Test_PHPUnit_Db_Connection($db,
  14.                                                       'database_schema_name');
  15.         $databaseTester = new Zend_Test_PHPUnit_Db_SimpleTester($connection);
  16.
  17.         $databaseFixture =
  18.                     new PHPUnit_Extensions_Database_DataSet_FlatXmlDataSet(
  19.                         dirname(__FILE__) . '/_files/initialUserFixture.xml'
  20.                     );
  21.
  22.         $databaseTester->setupDatabase($databaseFixture);
  23.     }
  24. }

Now the Flat XML dataset "initialUserFixture.xml" is used to set the database into an initial state before each test, exactly as the DatabaseTestCase works internally.

Using the Database Testing Adapter

There are times when you don't want to test parts of your application with a real database, but are forced to because of coupling. The Zend_Test_DbAdapter offers a convenient way to use a implementation of Zend_Db_Adapter_Abstract without having to open a database connection. Furthermore this Adapter is very easy to mock from within your PHPUnit testsuite, since it requires no constructor arguments.

The Test Adapter acts as a stack for various database results. Its order of results have to be userland implemented, which might be a tedious task for tests that call many different database queries, but its just the right helper for tests where only a handful of queries are executed and you know the exact order of the results that have to be returned to your userland code.

  1. $adapter   = new Zend_Test_DbAdapter();
  2. $stmt1Rows = array(array('foo' => 'bar'), array('foo' => 'baz'));
  3. $stmt1     = Zend_Test_DbStatement::createSelectStatement($stmt1Rows);
  4. $adapter->appendStatementToStack($stmt1);
  5.
  6. $stmt2Rows = array(array('foo' => 'bar'), array('foo' => 'baz'));
  7. $stmt2     = Zend_Test_DbStatement::createSelectStatement($stmt2Rows);
  8. $adapter->appendStatementToStack($stmt2);
  9.
  10. $rs = $adapter->query('SELECT ...'); // Returns Statement 2
  11. while ($row = $rs->fetch()) {
  12.     echo $rs['foo']; // Prints "Bar", "Baz"
  13. }
  14. $rs = $adapter->query('SELECT ...'); // Returns Statement 1

Behaviour of any real database adapter is simulated as much as possible such that methods like fetchAll(), fetchObject(), fetchColumn and more are working for the test adapter.

You can also put INSERT, UPDATE and DELETE statement onto the result stack, these however only return a statement which allows to specifiy the result of $stmt->rowCount().

  1. $adapter = new Zend_Test_DbAdapter();
  2. $adapter->appendStatementToStack(
  3.     Zend_Test_DbStatement::createInsertStatement(1)
  4. );
  5. $adapter->appendStatementToStack(
  6.     Zend_Test_DbStatement::createUpdateStatement(2)
  7. );
  8. $adapter->appendStatementToStack(
  9.     Zend_Test_DbStatement::createDeleteStatement(10
  10. ));

By default the query profiler is enabled, so that you can retrieve the executed SQL statements and their bound parameters to check for the correctness of the execution.

  1. $adapter = new Zend_Test_DbAdapter();
  2. $stmt = $adapter->query("SELECT * FROM bugs");
  3.
  4. $qp = $adapter->getProfiler()->getLastQueryProfile();
  5.
  6. echo $qp->getQuerY(); // SELECT * FROM bugs

The test adapter never checks if the query specified is really of the type SELECT, DELETE, INSERT or UPDATE which is returned next from the stack. The correct order of returning the data has to be implemented by the user of the test adapter.

The Test adapter also specifies methods to simulate the use of the methods
 listTables(),  describeTables() and
 lastInsertId(). Additionally using the
 setQuoteIdentifierSymbol() you can specify which
symbol should be used for quoting, by default none is used.

Zend_Test_PHPUnit
Zend_Test
Zend Framework手册 中文版
Zend_Text
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Test
  • 简介
  • Zend_Test_PHPUnit
  • Zend_Test_PHPUnit_Db


Zend_Text - Zend Framework Manual

Zend_Test_PHPUnit_Db
Zend Framework Reference
Zend Framework手册 中文版
Zend_Text_Figlet

Zend_Text

Table of Contents
  • Zend_Text_Figlet
  • Zend_Text_Table
Zend_Test_PHPUnit_Db
Zend Framework Reference
Zend Framework手册 中文版
Zend_Text_Figlet
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


Zend_Text_Table - Zend Framework Manual

Zend_Text_Figlet
Zend_Text
Zend Framework手册 中文版
Zend_TimeSync

Zend_Text_Table

Zend_Text_Table is a component to create text based tables on the fly with different decorators. This can be helpful, if you either want to send structured data in text emails, which are used to have mono-spaced fonts, or to display table information in a CLI application. Zend_Text_Table supports multi-line columns, colspan and align as well.

Note: Encoding
 Zend_Text_Table expects your strings to be UTF-8 encoded by default. If this is not the case, you can either supply the character encoding as a parameter to the constructor or the setContent method of Zend_Text_Table_Column. Alternatively if you have a different encoding in the entire process, you can define the standard input charset with Zend_Text_Table::setInputCharset($charset). In case you need another output charset for the table, you can set this with Zend_Text_Table::setOutputCharset($charset).

A Zend_Text_Table object consists of rows, which contain columns, represented by Zend_Text_Table_Row and Zend_Text_Table_Column. When creating a table, you can supply an array with options for the table. Those are:

  • columnWidths (required): An array defining all columns width their widths in characters.

  • decorator: The decorator to use for the table borders. The default is unicode, but you may also specify ascii or give an instance of a custom decorator object.

  • padding: The left and right padding withing the columns in characters. The default padding is zero.

  • AutoSeparate: The way how the rows are separated with horizontal lines. The default is a separation between all rows. This is defined as a bitmask containing one ore more of the following constants of Zend_Text_Table:

    • Zend_Text_Table::AUTO_SEPARATE_NONE

    • Zend_Text_Table::AUTO_SEPARATE_HEADER

    • Zend_Text_Table::AUTO_SEPARATE_FOOTER

    • Zend_Text_Table::AUTO_SEPARATE_ALL

    Where header is always the first row, and the footer is always the last row.

Rows are simply added to the table by creating a new instance of Zend_Text_Table_Row, and appending it to the table via the appendRow method. Rows themselves have no options. You can also give an array to directly to the appendRow method, which then will automatically converted to a row object, containing multiple column objects.

The same way you can add columns to the rows. Create a new instance of Zend_Text_Table_Column and then either set the column options in the constructor or later with the set* methods. The first parameter is the content of the column which may have multiple lines, which in the best case are separated by just the \n character. The second parameter defines the align, which is left by default and can be one of the class constants of Zend_Text_Table_Column:

  • ALIGN_LEFT

  • ALIGN_CENTER

  • ALIGN_RIGHT

The third parameter is the colspan of the column. For example, when you choose "2" as colspan, the column will span over two columns of the table. The last parameter defines the encoding of the content, which should be supplied, if the content is neither ASCII nor UTF-8. To append the column to the row, you simply call appendColumn in your row object with the column object as parameter. Alternatively you can directly give a string to the appendColumn method.

To finally render the table, you can either use the render method of the table, or use the magic method __toString by doing echo $table; or $tableString = (string) $table.

Example #1 Using Zend_Text_Table

This example illustrates the basic use of Zend_Text_Table to create a simple table:

  1. $table = new Zend_Text_Table(array('columnWidths' => array(10, 20)));
  2.
  3. // Either simple
  4. $table->appendRow(array('Zend', 'Framework'));
  5.
  6. // Or verbose
  7. $row = new Zend_Text_Table_Row();
  8.
  9. $row->appendColumn(new Zend_Text_Table_Column('Zend'));
  10. $row->appendColumn(new Zend_Text_Table_Column('Framework'));
  11.
  12. $table->appendRow($row);
  13.
  14. echo $table;

This will result in the following output:

  1. ┌──────────┬────────────────────┐
  2. │Zend      │Framework           │
  3. └──────────┴────────────────────┘
Zend_Text_Figlet
Zend_Text
Zend Framework手册 中文版
Zend_TimeSync
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Text
  • Zend_Text_Figlet
  • Zend_Text_Table


Zend_Text_Figlet - Zend Framework Manual

Zend_Text
Zend_Text
Zend Framework手册 中文版
Zend_Text_Table

Zend_Text_Figlet

Zend_Text_Figlet is a component which enables developers to create a so called FIGlet text. A FIGlet text is a string, which is represented as ASCII art. FIGlets use a special font format, called FLT (FigLet Font). By default, one standard font is shipped with Zend_Text_Figlet, but you can download additional fonts at » http://www.figlet.org.

Note: Compressed fonts
 Zend_Text_Figlet supports gzipped fonts. This means that you can take an .flf file and gzip it. To allow Zend_Text_Figlet to recognize this, the gzipped font must have the extension .gz. Further, to be able to use gzipped fonts, you have to have enabled the GZIP extension of PHP.

Note: Encoding
 Zend_Text_Figlet expects your strings to be UTF-8 encoded by default. If this is not the case, you can supply the character encoding as second parameter to the render() method.

You can define multiple options for a FIGlet. When instantiating Zend_Text_Figlet, you can supply an array or an instance of Zend_Config.

  • font - Defines the font which should be used for rendering. If not defines, the built-in font will be used.

  • outputWidth - Defines the maximum width of the output string. This is used for word-wrap as well as justification. Beware of too small values, they may result in an undefined behaviour. The default value is 80.

  • handleParagraphs - A boolean which indicates, how new lines are handled. When set to TRUE, single new lines are ignored and instead treated as single spaces. Only multiple new lines will be handled as such. The default value is FALSE.

  • justification - May be one of the values of Zend_Text_Figlet::JUSTIFICATION_*. There is JUSTIFICATION_LEFT, JUSTIFICATION_CENTER and JUSTIFICATION_RIGHT The default justification is defined by the rightToLeft value.

  • rightToLeft - Defines in which direction the text is written. May be either Zend_Text_Figlet::DIRECTION_LEFT_TO_RIGHT or Zend_Text_Figlet::DIRECTION_RIGHT_TO_LEFT. By default the setting of the font file is used. When justification is not defined, a text written from right-to-left is automatically right-aligned.

  • smushMode - An integer bitfield which defines, how the single characters are smushed together. Can be the sum of multiple values from Zend_Text_Figlet::SM_*. There are the following smush modes: SM_EQUAL, SM_LOWLINE, SM_HIERARCHY, SM_PAIR, SM_BIGX, SM_HARDBLANK, SM_KERN and SM_SMUSH. A value of 0 doesn't disable the entire smushing, but forces SM_KERN to be applied, while a value of -1 disables it. An explanation of the different smush modes can be found » here. By default the setting of the font file is used. The smush mode option is normally used only by font designers testing the various layoutmodes with a new font.

Example #1 Using Zend_Text_Figlet

This example illustrates the basic use of Zend_Text_Figlet to create a simple FIGlet text:

  1. $figlet = new Zend_Text_Figlet();
  2. echo $figlet->render('Zend');

Assuming you are using a monospace font, this would look as follows:

  1. ______    ______    _  __   ______
  2.  |__  //   |  ___||  | \| || |  __ \\
  3.    / //    | ||__    |  ' || | |  \ ||
  4.   / //__   | ||___   | .  || | |__/ ||
  5.  /_____||  |_____||  |_|\_|| |_____//
  6.  `-----`'  `-----`   `-` -`'  -----`
Zend_Text
Zend_Text
Zend Framework手册 中文版
Zend_Text_Table
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Text
  • Zend_Text_Figlet
  • Zend_Text_Table


Zend_TimeSync - Zend Framework Manual

Zend_Text_Table
Zend Framework Reference
Zend Framework手册 中文版
Introduction

Zend_TimeSync

Table of Contents
  • Introduction
  • Working with Zend_TimeSync
Zend_Text_Table
Zend Framework Reference
Zend Framework手册 中文版
Introduction
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


Introduction - Zend Framework Manual

Zend_TimeSync
Zend_TimeSync
Zend Framework手册 中文版
Working with Zend_TimeSync

Introduction

Zend_TimeSync is able to receive internet or network time from a time server using the NTP or SNTP protocol. With Zend_TimeSync, Zend Framework is able to act independently from the time settings of the server where it is running.

To be independent from the actual time of the server, Zend_TimeSync works with the difference of the real time which is sent through NTP or SNTP and the internal server's time.

Note: Background
 Zend_TimeSync is not able to change the server's time, but it will return a Zend_Date instance from which the difference from the server's time can be worked with.

Why Zend_TimeSync ?

So why would someone use Zend_TimeSync ?

Normally every server within a multi-server farm will have a service running which synchronizes its own time with a time server. So within a standard environment it should not be necessary to use Zend_TimeSync. But it can become handy if there is no service available and if you don't have the right to install such a service.

Here are some example use cases, for which Zend_TimeSync is perfect suited:

  • Server without time service

    If your application is running on a server and this server does not have any time service running, it may make sense to use Zend_TimeSync in your application.

  • Separate database server

    If your database is running on a different server and this server is not connected with NTP or SNTP to the application server, you might have problems using storing and using time stamp data.

  • Multiple servers

    If your application is running on more than one server and these servers' time bases are not syncronized, you can expect problems within your application when part of the application is coming from one server and another part from another server.

  • Batch processing

    If you want to work with a time service within a batch file or within a command line application, Zend_TimeSync may be of use.

Zend_TimeSync may provide a good solution in all of these cases and can be used if you are unable to run any services on your server.

What is NTP ?

The Network Time Protocol (NTP) is a protocol for synchronizing multiple systems' clocks over packet-switched, variable-latency data networks. NTP uses UDP port 123 as its transport layer. See the » wikipedia article for details about this protocol.

What is SNTP?

The Simple Network Time Protocol (SNTP) is a protocol synchronizing multiple systems' clocks over packet-switched, variable-latency data networks. SNTP uses UDP port 37 as its transport layer. It is closely related to the Network Time Protocol, but simpler.

Problematic usage

Be warned that when you are using Zend_TimeSync you will have to think about some details related to the structure of time sync and the internet itself. Correct usage and best practices will be described here. Read carefully before you begin using Zend_TimeSync.

Decide which server to use

You should select the time server that you want to use very carefully according to the following criteria:

  • Distance

    The distance from your application server to the time server. If your server is in Europe, it would make little sense to select a time server in Tahiti. Always select a server which is not far away. This reduces the request time and overall network load.

  • Speed

    How long it takes to receive the request is also relevant. Try different servers to get the best result. If you are requesting a server which is never accessible, you will always have an unnecessary delay.

  • Splitting

    Do not always use the same server. All time servers will lock out requests from servers that are flooding the server. If your application requires heavy use of time servers, you should consider one of the pools described later.

So where can you find a time server? Generally you can use any timeserver you can connect to. This can be a time server within your LAN or any public time server you have access to. If you decide to use a public time server, you should consider using a server pool. Server pools are public addresses from which you will get a random, pooled time server by requesting the time. This way you will not have to split your requests. There are public server pools available for many regions which you may use to avoid problems mentioned above.

See » pool.ntp.org to find your nearest server pool. For example, if your server is located within Germany you can connect to 0.europe.pool.ntp.org.

Zend_TimeSync
Zend_TimeSync
Zend Framework手册 中文版
Working with Zend_TimeSync
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_TimeSync
  • Introduction
  • Working with Zend_TimeSync


Working with Zend_TimeSync - Zend Framework Manual

Introduction
Zend_TimeSync
Zend Framework手册 中文版
Zend_Tool

Working with Zend_TimeSync

Zend_TimeSync can return the actual time from any given NTP or SNTP time server. It can automatically handle multiple servers and provides a simple interface.

Note: All examples in this chapter use a public, generic time server: 0.europe.pool.ntp.org. You should use a public, generic time server which is close to your application server. See » http://www.pool.ntp.org for information.

Generic Time Server Request

Requesting the time from a time server is simple. First, you provide the time server from which you want to request the time.

  1. $server = new Zend_TimeSync('0.pool.ntp.org');
  2.
  3. print $server->getDate()->getIso();

So what is happening in the background of Zend_TimeSync? First the syntax of the time server is checked. In our example, '0.pool.ntp.org' is checked and recognised as a possible address for a time server. Then when calling getDate() the actual set time server is requested and it will return its own time. Zend_TimeSync then calculates the difference to the actual time of the server running the script and returns a Zend_Date object with the correct time.

For details about Zend_Date and its methods see the Zend_Date documentation.

Multiple Time Servers

Not all time servers are always available to return their time. Servers may be unavailable during maintenance, for example. When the time cannot be requested from the time server, you will get an exception.

Zend_TimeSync is a simple solution that can handle multiple time servers and supports an automatic fallback mechanism. There are two supported ways; you can either specify an array of time servers when creating the instance, or you can add additional time servers to the instance using the addServer() method.

  1. $server = new Zend_TimeSync(array('0.pool.ntp.org',
  2.                                   '1.pool.ntp.org',
  3.                                   '2.pool.ntp.org'));
  4. $server->addServer('3.pool.ntp.org');
  5.
  6. print $server->getDate()->getIso();

There is no limit to the number of time servers you can add. When a time server can not be reached, Zend_TimeSync will fallback and try to connect to the next time server.

When you supply more than one time server- which is considered a best practice for Zend_TimeSync- you should name each server. You can name your servers with array keys, with the second parameter at instantiation, or with the second parameter when adding another time server.

  1. $server = new Zend_TimeSync(array('generic'  => '0.pool.ntp.org',
  2.                                   'fallback' => '1.pool.ntp.org',
  3.                                   'reserve'  => '2.pool.ntp.org'));
  4. $server->addServer('3.pool.ntp.org', 'additional');
  5.
  6. print $server->getDate()->getIso();

Naming the time servers allows you to request a specific time server as we will see later in this chapter.

Protocols of Time Servers

There are different types of time servers. Most public time servers use the NTP protocol. But there are other time synchronization protocols available.

You set the proper protocol in the address of the time server. There are two protocols which are supported by Zend_TimeSync: NTP and SNTP. The default protocol is NTP. If you are using NTP, you can omit the protocol in the address as demonstrated in the previous examples.

  1. $server = new Zend_TimeSync(array('generic'  => 'ntp:\\0.pool.ntp.org',
  2.                                   'fallback' => 'ntp:\\1.pool.ntp.org',
  3.                                   'reserve'  => 'ntp:\\2.pool.ntp.org'));
  4. $server->addServer('sntp:\\internal.myserver.com', 'additional');
  5.
  6. print $server->getDate()->getIso();

Zend_TimeSync can handle mixed time servers. So you are not restricted to only one protocol; you can add any server independently from its protocol.

Using Ports for Time Servers

As with every protocol within the world wide web, the NTP and SNTP protocols use standard ports. NTP uses port 123 and SNTP uses port 37.

But sometimes the port that the protocols use differs from the standard one. You can define the port which has to be used for each server within the address. Just add the number of the port after the address. If no port is defined, then Zend_TimeSync will use the standard port.

  1. $server = new Zend_TimeSync(array('generic'  => 'ntp:\\0.pool.ntp.org:200',
  2.                                   'fallback' => 'ntp:\\1.pool.ntp.org'));
  3. $server->addServer('sntp:\\internal.myserver.com:399', 'additional');
  4.
  5. print $server->getDate()->getIso();

Time Servers Options

There is only one option within Zend_TimeSync which will be used internally: timeout. You can set any self-defined option you are in need of and request it, however.

The option timeout defines the number of seconds after which a connection is detected as broken when there was no response. The default value is 1, which means that Zend_TimeSync will fallback to the next time server if the requested time server does not respond in one second.

With the setOptions() method, you can set any option. This function accepts an array where the key is the option to set and the value is the value of that option. Any previously set option will be overwritten by the new value. If you want to know which options are set, use the getOptions() method. It accepts either a key which returns the given option if specified, or, if no key is set, it will return all set options.

  1. Zend_TimeSync::setOptions(array('timeout' => 3, 'myoption' => 'timesync'));
  2. $server = new Zend_TimeSync(array('generic'  => 'ntp:\\0.pool.ntp.org',
  3.                                   'fallback' => 'ntp:\\1.pool.ntp.org'));
  4. $server->addServer('sntp:\\internal.myserver.com', 'additional');
  5.
  6. print $server->getDate()->getIso();
  7. print_r(Zend_TimeSync::getOptions();
  8. print "Timeout = " . Zend_TimeSync::getOptions('timeout');

As you can see, the options for Zend_TimeSync are static. Each instance of Zend_TimeSync will use the same options.

Using Different Time Servers

Zend_TimeSync's default behavior for requesting a time is to request it from the first given server. But sometimes it is useful to set a different time server from which to request the time. This can be done with the setServer() method. To define the used time server set the alias as a parameter within the method. To get the actual used time server call the getServer() method. It accepts an alias as a parameter which defines the time server to be returned. If no parameter is given, the current time server will be returned.

  1. $server = new Zend_TimeSync(array('generic'  => 'ntp:\\0.pool.ntp.org',
  2.                                   'fallback' => 'ntp:\\1.pool.ntp.org'));
  3. $server->addServer('sntp:\\internal.myserver.com', 'additional');
  4.
  5. $actual = $server->getServer();
  6. $server = $server->setServer('additional');

Information from Time Servers

Time servers not only offer the time itself, but also additional information. You can get this information with the getInfo() method.

  1. $server = new Zend_TimeSync(array('generic'  => 'ntp:\\0.pool.ntp.org',
  2.                                   'fallback' => 'ntp:\\1.pool.ntp.org'));
  3.
  4. print_r ($server->getInfo());

The returned information differs with the protocol used and can also differ with the server used.

Handling Exceptions

Exceptions are collected for all time servers and returned as an array. So you can iterate through all thrown exceptions as shown in the following example:

  1. $serverlist = array(
  2.         // invalid servers
  3.         'invalid_a'  => 'ntp://a.foo.bar.org',
  4.         'invalid_b'  => 'sntp://b.foo.bar.org',
  5. );
  6.
  7. $server = new Zend_TimeSync($serverlist);
  8.
  9. try {
  10.     $result = $server->getDate();
  11.     echo $result->getIso();
  12. } catch (Zend_TimeSync_Exception $e) {
  13.
  14.     $exceptions = $e->get();
  15.
  16.     foreach ($exceptions as $key => $myException) {
  17.         echo $myException->getMessage();
  18.         echo '<br />';
  19.     }
  20. }
Introduction
Zend_TimeSync
Zend Framework手册 中文版
Zend_Tool
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_TimeSync
  • Introduction
  • Working with Zend_TimeSync


Zend_Tool - Zend Framework Manual

Working with Zend_TimeSync
Zend Framework Reference
Zend Framework手册 中文版
Using Zend_Tool On The Command Line

Zend_Tool

Table of Contents
  • Using Zend_Tool On The Command Line
  • Extending Zend_Tool
Working with Zend_TimeSync
Zend Framework Reference
Zend Framework手册 中文版
Using Zend_Tool On The Command Line
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


Using Zend_Tool On The Command Line - Zend Framework Manual

Zend_Tool
Zend_Tool
Zend Framework手册 中文版
Extending Zend_Tool

Using Zend_Tool On The Command Line

The CLI, or command line tool (internally known as the console tool), is currently the primary interface for dispatching Zend_Tool requests. With the CLI tool, developers can issue tooling requests inside the "command line window", also commonly known as a "terminal" window. This environment is predominant in the *nix environment, but also has a common implementation in windows with the cmd.exe, console2 and also with the Cygwin project.

Installation

Download And Go

First download Zend Framework. This can be done by going to framework.zend.com and downloading the latest release. After you've downloaded the package and placed it on your system. The next step is to make the zf command available to your system. The easiest way to do this, is to copy the proper files from the bin/ directory of the download, and place these files within the same directory as the location of the php cli binary.

Installing Via Pear

To install via PEAR, you must use the 3rd party zfcampus.org site to retrieve the latest Zend Framework PEAR package. These packages are typically built within a day of an official Zend Framework release. The benefit of installing via the PEAR package manager is that during the install process, the ZF library will end up on the include_path, and the zf.php and zf scripts will end up in a place on your system that will allow you to run them without any additional setup.

  1. pear discover-channel pear.zfcampus.org
  2. pear install zfcampus/zf

That is it. After the initial install, you should be able to continue on by running the zf command. Go good way to check to see if it't there is to run zf --help

Installing by Hand

Installing by hand refers to the process of forcing the zf.php and Zend Framework library to work together when they are placed in non-convential places, or at least, in a place that your system cannot dispatch from easily (typical of programs in your system PATH).

If you are on a *nix or mac system, you can also create a link from somewhere in your path to the zf.sh file. If you do this, you do not need to worry about having Zend Framework's library on your include_path, as the zf.php and zf.sh files will be able to access the library relative to where they are (meaning the ./bin/ files are ../library/ relative to the Zend Framework library).

There are a number of other options available for setting up the zf.php and library on your system. These options revolve around setting specific environment variables. These are described in the later section on "customizing the CLI environement". The environment variables for setting the zf.php include_path, ZF_INCLUDE_PATH and ZF_INCLUDE_PATH_PREPEND, are the ones of most interest.

General Purpose Commands

Version

This will show the current version number of the copy of Zend Framework the zf.php tool is using.

  1. zf show version

Built-in Help

The built-in help system is the primary place where you can get up-to-date information on what your system is capable of doing. The help system is dynamic in that as providers are added to your system, they are automatically dispatchable, and as such, the parameters required to run them will be in the help screen. The easiest way to retrieve the help screen is the following:

  1. zf --help

This will give you an overview of the various capabilities of the system. Sometimes, there are more finite commands than can be run, and to gain more information about these, you might have to run a more specialized help command. For specialized help, simply replace any of the elements of the command with a "?". This will tell the help system that you want more information about what commands can go in place of the question mark. For example:

  1. zf ? controller

The above means "show me all 'actions' for the provider 'controller'"; while the following:

  1. zf show ?

means "show me all providers that support the 'show' action". This works for drilling down into options as well as you can see in the following examples:

  1. zf show version.? (show any specialties)
  2. zf show version ? (show any options)

Manifest

This will show what information is in the tooling systems manifest. This is more important for provider developers than casual users of the tooling system.

  1. zf show manifest

Project Specific Commands

Project

The project provider is the first command you might want to run. This will setup the basic structure of your application. This is required before any of the other providers can be executed.

  1. zf create project MyProjectName

This will create a project in a directory called ./MyProjectName. From this point on, it is important to note that any subsequent commands on the command line must be issued from within the project directory you had just created. So, after creation, changing into that directory is required.

Project

The module provider allows for the easy creation of a Zend Framework module. A module follows the hMVC pattern loosely. When creating modules, it will take the same structure used at the application/ level, and duplicate it inside of the chosen name for your module, inside of the "modules" directory of the application/ directory without duplicating the modules directory itself. For example:

  1. zf create module Blog

This will create a module named Blog at application/modules/Blog, and all of the artifacts that a module will need.

Controller

The controller provider is responsible for creating (mostly) empty controllers as well as their corresponding view script directories and files. To utilize it to create an 'Auth' controlller, for example, execute:

  1. zf create controller Auth

This will create a controller named Auth, specifically it will create a file at application/controllers/AuthController.php with the AuthController inside. If you wish to create a controller for a module, use any of the following:

  1. zf create controller Post 1 Blog
  2. zf create controller Post -m Blog
  3. zf create controller Post --module=Blog

Note: In the first command, 1 is the value for the "includeIndexAction" flag.

Action

To create an action within an existing controller:

  1. zf create action login Auth
  2. zf create action login -c Auth
  3. zf create action login --controller-name=Auth

View

To create a view outside of the normal controller/action creation, you would use one of the following:

  1. zf create view Auth my-script-name
  2. zf create view -c Auth -a my-script-name

This will create a view script in the controller folder of Auth.

Model

The model provider is only responsible for creating the proper model files, with the proper name inside the application folder. For example

  1. zf create model User

If you wish to create a model within a specific module:

  1. zf create model Post -m Blog

The above will create a 'Post' model inside of the 'Blog' module.

Form

The form provider is only responsible for creating the proper form file and init() method, with the proper name inside the application folder. For example:

  1. zf create form Auth

If you wish to create a model within a specific module:

  1. zf create form Comment -m Blog

The above will create a 'Comment' form inside of the 'Blog' module.

DbAdapter

To configure a DbAdapter, you will need to provide the information as a url encoded string. This string needs to be in quotes on the command line.

For example, to enter the following information:

  • adapter: Pdo_Mysql

  • username: test

  • password: test

  • dbname: test

The following will have to be run on the command line:

  1. zf configure dbadapter "adapter=Pdo_Mysql&username=test&password=test&dbname=test"

This assumes you wish to store this information inside of the 'production' space of the application configuration file. The following will demonstrate an sqlite configuration, in the 'development' section of the application config file.

  1. zf configure dbadapter "adapter=Pdo_Sqlite&dbname=../data/test.db" development
  2. zf configure dbadapter "adapter=Pdo_Sqlite&dbname=../data/test.db" -s development

DbTable

The DbTable provider is responsible for creating Zend_Db_Table model/data access files for your application to consume, with the proper class name, and in the proper location in the application. The two important pieces of information are the DbTable name, and the actual database table name. For example:

  1. zf create dbtable User user
  2. zf create dbtable User -a user
  3.
  4. // also accepts a force option to overwrite existing files
  5. zf create dbtable User user -f
  6. zf create dbtable User user --force-override

The DbTable provider is also capable of creating the proper files by scanning the database configured with the above DbAdapter provider.

  1. zf create dbtable.from-database

When executing the above, it might make sense to use the pretend / "-p" flag first so that you can see what would be done, and what tables can be found in the database.

  1. zf -p create dbtable.from-database

Layout

Currently, the only supported action for layouts is simply to enable them will setup the proper keys in the application.ini file for the application resource to work, and create the proper directories and layout.phtml file.

  1. zf enable layout

Environment Customization

The Storage Directory

The storage directory is important so that providers may have a place to find custom user generated logic that might change the way they behave. One example can be found below is the placement of a custom project profile file.

  1. zf --setup storage-directory

The Configuration File

This will create the proper zf.ini file. This should be run after zf --setup storage-directory. If it is not, it will be located inside the users home directory. If it is, it will be located inside the users storage directory.

  1. zf --setup config-file

Environment Locations

These should be set if you wish to override the default places where zf will attempt to read their values.

  • ZF_HOME

    • the directory this tool will look for a home directory

    • directory must exist

    • search order:

      • ZF_HOME environment variable

      • HOME environment variable

      • then HOMEPATH environment variable

  • ZF_STORAGE_DIRECTORY

    • where this tool will look for a storage directory

    • directory must exist

    • search order:

      • ZF_STORAGE_DIRECTORY environment variable

      • $homeDirectory/.zf/ directory

  • ZF_CONFIG_FILE

    • where this tool will look for a configuration file

    • search order:

      • ZF_CONFIG_FILE environment variable

      • $homeDirectory/.zf.ini file if it exists

      • $storageDirectory/zf.ini file if it exists

  • ZF_INCLUDE_PATH

    • set the include_path for this tool to use this value

    • original behavior:

      • use php's include_path to find ZF

      • use the ZF_INCLUDE_PATH environment variable

      • use the path ../library (relative to zf.php) to find ZF

  • ZF_INCLUDE_PATH_PREPEND

    • prepend the current php.ini include_path with this value

Zend_Tool
Zend_Tool
Zend Framework手册 中文版
Extending Zend_Tool
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Tool
  • Using Zend_Tool On The Command Line
  • Extending Zend_Tool


Extending Zend_Tool - Zend Framework Manual

Using Zend_Tool On The Command Line
Zend_Tool
Zend Framework手册 中文版
Zend_Tool_Framework

Extending Zend_Tool

Overview of Zend_Tool

Zend_Tool_Framework is a framework for exposing common functionalities such as the creation of project scaffolds, code generation, search index generation, and much more. Functionality may be written and exposed via PHP classes dropped into the PHP include_path, providing incredible flexibility of implementation. The functionality may then be consumed by writing implementation and/or protocol-specific clients -- such as console clients, XML-RPC, SOAP, and much more.

Zend_Tool_Project builds on and extends the capabilities of Zend_Tool_Framework to that of managing a "project". In general, a "project" is a planned endeavor or an initiative. In the computer world, projects generally are a collection of resources. These resources can be files, directories, databases, schemas, images, styles, and more.

Zend_Tool_Framework Extensions

Overall Architecture

Zend_Tool_Framework provides the following:

  • Common interfaces and abstracts that allow developers to create functionality and capabilities that are dispatchable by tooling clients.

  • Base client functionality and a concrete console implementation that connect external tools and interfaces to the Zend_Tool_Framework. The Console client may be used in CLI environments such as unix shells and the Windows console.

  • "Provider" and "Manifest" interfaces that can be utilized by the tooling system. "Providers" represent the functional aspect of the framework, and define the actions that tooling clients may call. "Manifests" act as metadata registries that provide additional context for the various defined providers.

  • An introspective loading system that will scan the environment for providers and determine what is required to dispatch them.

  • A standard set of system providers that allow the system to report what the full capabilities of the system are as well as provide useful feedback. This also includes a comprehensive "Help System".

Definitions that you should be aware of through this manual with respect to Zend_Tool_Framework include:

  • Zend_Tool_Framework - The framework which exposes tooling capabilities.

  • Tooling Client - A developer tool that connects to and consumes Zend_Tool_Framework.

  • Client - The subsystem of Zend_Tool_Framework that exposes an interface such that tooling clients can connect, query and execute commands.

  • Console Client / Command Line Interface / zf.php - The tooling client for the command line.

  • Provider - A subsystem and a collection of built-in functionality that the framework exports.

  • Manifest - A subsystem for defining, organizing, and disseminating provider requirement data.

  • Zend_Tool_Project Provider - A set of providers specifically for creating and maintaining Zend Framework-based projects.

Understanding the CLI Client

The CLI, or command line tool (internally known as the console tool), is currently the primary interface for dispatching Zend_Tool requests. With the CLI tool, developers can issue tooling requests inside the "command line windows", also commonly known as a "terminal" window. This environment is predominant in the *nix environment, but also has a common implementation in windows with the cmd.exe, console2 and also with the Cygwin project.

Setting up the CLI tool

To issue tooling requests via the command line client, you first need to set up the client so that your system can handle the "zf" command. The command line client, for all intents and purposes, is the .sh or .bat file that is provided with your Zend Framework distribution. In trunk, it can be found here: » http://framework.zend.com/svn/framework/standard/trunk/bin/.

As you can see, there are 3 files in the /bin/ directory: a zf.php, zf.sh, and zf.bat. The zf.sh and the zf.bat are the operating system specific client wrappers: zf.sh for the *nix environment, and zf.bat for the Win32 environment. These client wrappers are responsible for finding the proper php.exe, finding the zf.php, and passing on the client request. The zf.php is the responsible for handling understanding your environment, constructing the proper include_path, and passing what is provided on the command line to the proper library component for dispatching.

Ultimately, you want to ensure two things to make everything work regardless of the operating system you are on:

  1. zf.sh/zf.bat is reachable from your system path. This is the ability to call zf from anywhere on your command line, regardless of what your current working directory is.

  2. ZendFramework/library is in your include_path.

Note: Note: while the above are the most ideal requirements, you can simply download Zend Framework and expect it to work as ./path/to/zf.php some command.

Setting up the CLI tool on Unix-like Systems

The most common setup in the *nix environment, is to copy the zf.sh and zf.php into the same directory as your PHP binary. This can generally be found in one of the following places:

  1. /usr/bin
  2. /usr/local/bin
  3. /usr/local/ZendServer/bin/
  4. /Applications/ZendServer/bin/

To find out the location of your PHP binary, you can execute 'which php' on the command line. This will return the location of the PHP binary you will be using to run PHP scripts in this environment.

The next order of business is to ensure that Zend Framework library is set up correctly inside of the system PHP include_path. To find out where your include_path is located, you can execute php -i and look for the include_path variable, or more succinctly, execute php -i | grep include_path. Once you have found where your include_path is located (this will generally be something like /usr/lib/php, /usr/share/php, /usr/local/lib/php, or similar), ensure that the contents of the /library/ directory are put inside your include_path specified directory.

Once you have done those two things, you should be able to issue a command and get back the proper response like this:

< class="inlinemediaobject">

If you do not see this type of output, go back and check your setup to ensure you have all of the necessary pieces in the proper place.

There are a couple of alternative setups you might want to employ depending on your servers configuration, your level of access, or for other reasons.

Alternative Setup involves keeping the Zend Framework download together as is, and creating a link from a PATH location to the zf.sh. What this means is you can place the contents of the ZendFramework download into a location such as /usr/local/share/ZendFramework, or more locally like /home/username/lib/ZendFramework, and creating a symbolic link to the zf.sh.

Assuming you want to put the link inside /usr/local/bin (this could also work for placing the link inside /home/username/bin/ for example) you would issue a command similar to this:

  1. ln -s /usr/local/share/ZendFramework/bin/zf.sh /usr/local/bin/zf
  2.
  3. # OR (for example)
  4. ln -s /home/username/lib/ZendFramework/bin/zf.sh /home/username/bin/zf

This will create a link which you should be able to access globally on the command line.

Setting up the CLI tool on Windows

The most common setup in the Windows Win32 environment, is to copy the zf.bat and zf.php into the same directory as your PHP binary. This can generally be found in one of the following places:

  1. C:\PHP
  2. C:\Program Files\ZendServer\bin\
  3. C:\WAMP\PHP\bin

You should be able to run php.exe on the command line. If you are not able to, first check the documentation that came with your PHP distribution, or ensure that the path to php.exe is in your Windows PATH environment variable.

The next order of business is to ensure that Zend Framework library is set up correctly inside of the system PHP include_path. To find out where your include_path is located, you can type php -i and look for the include_path variable, or more succinctly execute php -i | grep include_path if you have Cygwin setup with grep available. Once you have found where your include_path is located (this will generally be something like C:\PHP\pear, C:\PHP\share, C:\Program%20Files\ZendServer\share or similar), ensure that the contents of the library/ directory are put inside your include_path specified directory.

Once you have done those two things, you should be able to issue a command and get back the proper response like this:

< class="inlinemediaobject">

If you do not see this type of output, go back and check your setup to ensure you have all of the necessary pieces in the proper place.

There are a couple of alternative setups you might want to employ depending on your server's configuration, your level of access, or for other reasons.

Alternative Setup involves keeping the Zend Framework download together as is, and altering both your system PATH as well as the php.ini file. In your user's environment, make sure to add C:\Path\To\ZendFramework\bin, so that your zf.bat file is executable. Also, alter the php.ini file to ensure that C:\Path\To\ZendFramework\library is in your include_path.

Other Setup Considerations

If for some reason you do not want Zend Framework library inside your include_path, there is another option. There are two special environment variables that zf.php will utilize to determine the location of your Zend Framework installation.

The first is ZEND_TOOL_INCLUDE_PATH_PREPEND, which will prepend the value of this environment variable to the system (php.ini) include_path before loading the client.

Alternatively, you might want to use ZEND_TOOL_INCLUDE_PATH to completely replace the system include_path for one that makes sense specifically for the zf command line tool.

Creating Providers

In general, a provider, on its own, is nothing more than the shell for a developer to bundle up some capabilities they wish to dispatch with the command line (or other) clients. It is an analogue to what a "controller" is inside of your MVC application.

How Zend Tool finds your Providers

By default Zend Tool uses the BasicLoader to find all the providers that you can run. It recursivly iterates all include path directories and opens all files that end with "Manifest.php" or "Provider.php". All classes in these files are inspected if they implement either Zend_Tool_Framework_Provider_Interface or Zend_Tool_Framework_Manifest_ProviderManifestable. Instances of the provider interface make up for the real functionality and all their public methods are accessible as provider actions. The ProviderManifestable interface however requires the implementation of a method getProviders() which returns an array of instantiated provider interface instances.

The following naming rules apply on how you can access the providers that were found by the IncludePathLoader:

  • The last part of your classname split by underscore is used for the provider name, e.g. "My_Provider_Hello" leads to your provider being accessible by the name "hello".

  • If your provider has a method getName() it will be used instead of the previous method to determine the name.

  • If your provider has "Provider" as prefix, e.g. it is called My_HelloProvider it will be stripped from the name so that the provider will be called "hello".

Note: The IncludePathLoader does not follow symlinks, that means you cannot link provider functionality into your include paths, they have to be physically present in the include paths.

Example #1 Exposing Your Providers with a Manifest

You can expose your providers to Zend Tool by offering a manifest with a special filename ending with "Manifest.php". A Provider Manifest is an implementation of the Zend_Tool_Framework_Manifest_ProviderManifestable and requires the getProviders() method to return an array of instantiated providers. In anticipation of our first own provider My_Component_HelloProvider we will create the following manifest:

  1. class My_Component_Manifest
  2.     implements Zend_Tool_Framework_Manifest_ProviderManifestable
  3. {
  4.     public function getProviders()
  5.     {
  6.         return array(
  7.             new My_Component_HelloProvider()
  8.         );
  9.     }
  10. }

Basic Instructions for Creating Providers

As an example, if a developer wants to add the capability of showing the version of a datafile that his 3rd party component is working from, there is only one class the developer would need to implement. Assuming the component is called My_Component, he would create a class named My_Component_HelloProvider in a file named HelloProvider.php somewhere on the include_path. This class would implement Zend_Tool_Framework_Provider_Interface, and the body of this file would only have to look like the following:

  1. class My_Component_HelloProvider
  2.     implements Zend_Tool_Framework_Provider_Interface
  3. {
  4.     public function say()
  5.     {
  6.         echo 'Hello from my provider!';
  7.     }
  8. }

Given that code above, and assuming the developer wishes to access this functionality through the console client, the call would look like this:

  1. % zf say hello
  2. Hello from my provider!

The response object

As discussed in the architecture section Zend Tool allows to hook different clients for using your Zend Tool providers. To keep compliant with different clients you should use the response object to return messages from your providers instead of using echo() or a similiar output mechanism. Rewritting our hello provider with this knowledge it looks like:

  1. class My_Component_HelloProvider
  2.     extends Zend_Tool_Framework_Provider_Abstract
  3. {
  4.     public function say()
  5.     {
  6.         $this->_registry->getResponse
  7.                         ->appendContent("Hello from my provider!");
  8.     }
  9. }

As you can see one has to extend the Zend_Tool_Framework_Provider_Abstract to gain access to the Registry which holds the Zend_Tool_Framework_Client_Response instance.

Advanced Development Information

Passing Variables to a Provider

The above "Hello World" example is great for simple commands, but what about something more advanced? As your scripting and tooling needs grow, you might find that you need the ability to accept variables. Much like function signatures have parameters, your tooling requests can also accept parameters.

Just as each tooling request can be isolated to a method within a class, the parameters of a tooling request can also be isolated in a very well known place. Parameters of the action methods of a provider can include the same parameters you want your client to utilize when calling that provider and action combination. For example, if you wanted to accept a name in the above example, you would probably do this in OO code:

  1. class My_Component_HelloProvider
  2.     implements Zend_Tool_Framework_Provider_Interface
  3. {
  4.     public function say($name = 'Ralph')
  5.     {
  6.         echo 'Hello' . $name . ', from my provider!';
  7.     }
  8. }

The above example can then be called via the command line zf say hello Joe. "Joe" will be supplied to the provider as a parameter of the method call. Also note, as you see that the parameter is optional, that means it is also optional on the command line, so that zf say hello will still work, and default to the name "Ralph".

Prompt the User for Input

There are cases when the workflow of your provider requires to prompt the user for input. This can be done by requesting the client to ask for more the required input by calling:

  1. class My_Component_HelloProvider
  2.     extends Zend_Tool_Framework_Provider_Abstract
  3. {
  4.     public function say($name = 'Ralph')
  5.     {
  6.         $nameResponse = $this->_registry
  7.                              ->getClient()
  8.                              ->promptInteractiveInput("Whats your name?");
  9.         $name = $name->getContent();
  10.
  11.         echo 'Hello' . $name . ', from my provider!';
  12.     }
  13. }

This command throws an exception if the current client is not able to handle interactive requests. In case of the default Console Client however you will be asked to enter the name.

Pretending to execute a Provider Action

Another interesting feature you might wish to implement is pretendability. Pretendabilty is the ability for your provider to "pretend" as if it is doing the requested action and provider combination and give the user as much information about what it would do without actually doing it. This might be an important notion when doing heavy database or filesystem modifications that the user might not otherwise want to do.

Pretendability is easy to implement. There are two parts to this feature: 1) marking the provider as having the ability to "pretend", and 2) checking the request to ensure the current request was indeed asked to be "pretended". This feature is demonstrated in the code sample below.

  1. class My_Component_HelloProvider
  2.     extends    Zend_Tool_Framework_Provider_Abstract
  3.     implements Zend_Tool_Framework_Provider_Pretendable
  4. {
  5.     public function say($name = 'Ralph')
  6.     {
  7.         if ($this->_registry->getRequest()->isPretend()) {
  8.             echo 'I would say hello to ' . $name . '.';
  9.         } else {
  10.             echo 'Hello' . $name . ', from my provider!';
  11.         }
  12.     }
  13. }

To run the provider in pretend mode just call:

  1. % zf --pretend say hello Ralph
  2. I would say hello Ralph.

Verbose and Debug modes

You can also run your provider actions in "verbose" or "debug" modes. The semantics in regard to this actions have to be implemented by you in the context of your provider. You can access debug or verbose modes with:

  1. class My_Component_HelloProvider
  2.     implements Zend_Tool_Framework_Provider_Interface
  3. {
  4.     public function say($name = 'Ralph')
  5.     {
  6.         if($this->_registry->getRequest()->isVerbose()) {
  7.             echo "Hello::say has been called\n";
  8.         }
  9.         if($this->_registry->getRequest()->isDebug()) {
  10.             syslog(LOG_INFO, "Hello::say has been called\n");
  11.         }
  12.     }
  13. }

Accessing User Config and Storage

Using the Enviroment variable ZF_CONFIG_FILE or the .zf.ini in your home directory you can inject configuration parameters into any Zend Tool provider. Access to this configuration is available via the registry that is passed to your provider if you extend Zend_Tool_Framework_Provider_Abstract.

  1. class My_Component_HelloProvider
  2.     extends Zend_Tool_Framework_Provider_Abstract
  3. {
  4.     public function say()
  5.     {
  6.         $username = $this->_registry->getConfig()->username;
  7.         if(!empty($username)) {
  8.             echo "Hello $username!";
  9.         } else {
  10.             echo "Hello!";
  11.         }
  12.     }
  13. }

The returned configuration is of the type Zend_Tool_Framework_Client_Config but internally the __get() and __set() magic methods proxy to a Zend_Config of the given configuration type.

The storage allows to save arbitrary data for later reference. This can be useful for batch processing tasks or for re-runs of your tasks. You can access the storage in a similar way like the configuration:

  1. class My_Component_HelloProvider
  2.     extends Zend_Tool_Framework_Provider_Abstract
  3. {
  4.     public function say()
  5.     {
  6.         $aValue = $this->_registry->getStorage()->get("myUsername");
  7.         echo "Hello $aValue!";
  8.     }
  9. }

The API of the storage is very simple:

  1. class Zend_Tool_Framework_Client_Storage
  2. {
  3.     public function setAdapter($adapter);
  4.     public function isEnabled();
  5.     public function put($name, $value);
  6.     public function get($name, $defaultValue=null);
  7.     public function has($name);
  8.     public function remove($name);
  9.     public function getStreamUri($name);
  10. }
Important

When designing your providers that are config or storage aware remember to check if the required user-config or storage keys really exist for a user. You won't run into fatal errors when none of these are provided though, since empty ones are created upon request.

Zend_Tool_Project Extensions

Zend_Tool_Project exposes a rich set of functionality and capabilities that make the task of creating new providers, specficially those targetting project easier and more manageable.

Overall Architecture

This same concept applies to Zend Framework projects. In Zend Framework projects, you have controllers, actions, views, models, databases and so on and so forth. In terms of Zend_Tool, we need a way to track these types of resources - thus Zend_Tool_Project.

Zend_Tool_Project is capable of tracking project resources throughout the development of a project. So, for example, if in one command you created a controller, and in the next command you wish to create an action within that controller, Zend_Tool_Project is gonna have to know about the controller file you created so that you can (in the next action), be able to append that action to it. This is what keeps our projects up to date and stateful.

Another important point to understand about projects is that typically, resources are organized in a hierarchical fashion. With that in mind, Zend_Tool_Project is capable of serializing the current project into a internal representation that allows it to keep track of not only what resources are part of a project at any given time, but also where they are in relation to one another.

Creating Providers

Project specific providers are created in the same fashion as plain framework providers, with one exception: project providers must extend the Zend_Tool_Project_Provider_Abstract. This class comes with some significant functionality that helps developers load existing project, obtian the profile object, and be able to search the profile, then later store any changes to the current project profile.

  1. class My_Component_HelloProvider
  2.     extends Zend_Tool_Project_Provider_Abstract
  3. {
  4.     public function say()
  5.     {
  6.         $profile = $this->_loadExistingProfile();
  7.
  8.         /* ... do project stuff here */
  9.
  10.         $this->_storeProfile();
  11.     }
  12. }
Using Zend_Tool On The Command Line
Zend_Tool
Zend Framework手册 中文版
Zend_Tool_Framework
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Tool
  • Using Zend_Tool On The Command Line
  • Extending Zend_Tool


Zend_Tool_Framework - Zend Framework Manual

Extending Zend_Tool
Zend Framework Reference
Zend Framework手册 中文版
Introduction

Zend_Tool_Framework

Table of Contents
  • Introduction
  • Using the CLI Tool
  • Architecture
  • Creating Providers to use with Zend_Tool_Framework
  • Shipped System Providers
  • Extending and Configuring Zend_Tool_Framework
Extending Zend_Tool
Zend Framework Reference
Zend Framework手册 中文版
Introduction
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


Introduction - Zend Framework Manual

Zend_Tool_Framework
Zend_Tool_Framework
Zend Framework手册 中文版
Using the CLI Tool

Introduction

Zend_Tool_Framework is a framework for exposing common functionalities such as the creation of project scaffolds, code generation, search index generation, and much more. Functionality may be written and exposed via PHP classes dropped into the PHP include_path, providing incredible flexibility of implementation. The functionality may then be consumed by writing implementation and/or protocol-specific clients -- such as console clients, XML-RPC, SOAP, and much more.

Zend_Tool_Framework provides the following:

  • Common interfaces and abstracts that allow developers to create functionality and capabilities that are dispatchable by tooling clients.

  • Base client functionality and a concrete console implementation that connect external tools and interfaces to the Zend_Tool_Framework. The Console client may be used in CLI environments such as unix shells and the Windows console.

  • "Provider" and "Manifest" interfaces that can be utilized by the tooling system. "Providers" represent the functional aspect of the framework, and define the actions that tooling clients may call. "Manifests" act as metadata registries that provide additional context for the various defined providers.

  • An introspective loading system that will scan the environment for providers and determine what is required to dispatch them.

  • A standard set of system providers that allow the system to report what the full capabilities of the system are as well as provide useful feedback. This also includes a comprehensive "Help System".

Definitions that you should be aware of through this manual with respect to Zend_Tool_Framework include:

  • Zend_Tool_Framework - The framework which exposes tooling capabilities.

  • Tooling Client - A developer tool that connects to and consumes Zend_Tool_Framework.

  • Client - The subsystem of Zend_Tool_Framework that exposes an interface such that tooling clients can connect, query and execute commands.

  • Console Client / Command Line Interface / zf.php - The tooling client for the command line.

  • Provider - A subsystem and a collection of built-in functionality that the framework exports.

  • Manifest - A subsystem for defining, organizing, and disseminating provider requirement data.

  • Zend_Tool_Project Provider - A set of providers specifically for creating and maintaining Zend Framework-based projects.

Zend_Tool_Framework
Zend_Tool_Framework
Zend Framework手册 中文版
Using the CLI Tool
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Tool_Framework
  • Introduction
  • Using the CLI Tool
  • Architecture
  • Creating Providers to use with Zend_Tool_Framework
  • Shipped System Providers
  • Extending and Configuring Zend_Tool_Framework


Using the CLI Tool - Zend Framework Manual

Introduction
Zend_Tool_Framework
Zend Framework手册 中文版
Architecture

Using the CLI Tool

The CLI, or command line tool (internally known as the console tool), is currently the primary interface for dispatching Zend_Tool requests. With the CLI tool, developers can issue tooling requests inside the "command line windows", also commonly known as a "terminal" window. This environment is predominant in the *nix environment, but also has a common implementation in windows with the cmd.exe, console2 and also with the Cygwin project.

Setting up the CLI tool

To issue tooling requests via the command line client, you first need to set up the client so that your system can handle the "zf" command. The command line client, for all intents and purposes, is the .sh or .bat file that is provided with your Zend Framework distribution. In trunk, it can be found here: » http://framework.zend.com/svn/framework/standard/trunk/bin/.

As you can see, there are 3 files in the /bin/ directory: a zf.php, zf.sh, and zf.bat. The zf.sh and the zf.bat are the operating system specific client wrappers: zf.sh for the *nix environment, and zf.bat for the Win32 environment. These client wrappers are responsible for finding the proper php.exe, finding the zf.php, and passing on the client request. The zf.php is the responsible for handling understanding your environment, constructing the proper include_path, and passing what is provided on the command line to the proper library component for dispatching.

Ultimately, you want to ensure two things to make everything work regardless of the operating system you are on:

  1. zf.sh/zf.bat is reachable from your system path. This is the ability to call zf from anywhere on your command line, regardless of what your current working directory is.

  2. ZendFramework/library is in your include_path.

Note: Note: while the above are the most ideal requirements, you can simply download Zend Framework and expect it to work as ./path/to/zf.php some command.

Setting up the CLI tool on Unix-like Systems

The most common setup in the *nix environment, is to copy the zf.sh and zf.php into the same directory as your PHP binary. This can generally be found in one of the following places:

  1. /usr/bin
  2. /usr/local/bin
  3. /usr/local/ZendServer/bin/
  4. /Applications/ZendServer/bin/

To find out the location of your PHP binary, you can execute 'which php' on the command line. This will return the location of the PHP binary you will be using to run PHP scripts in this environment.

The next order of business is to ensure that Zend Framework library is set up correctly inside of the system PHP include_path. To find out where your include_path is located, you can execute php -i and look for the include_path variable, or more succinctly, execute php -i | grep include_path. Once you have found where your include_path is located (this will generally be something like /usr/lib/php, /usr/share/php, /usr/local/lib/php, or similar), ensure that the contents of the /library/ directory are put inside your include_path specified directory.

Once you have done those two things, you should be able to issue a command and get back the proper response like this:

< class="inlinemediaobject">

If you do not see this type of output, go back and check your setup to ensure you have all of the necessary pieces in the proper place.

There are a couple of alternative setups you might want to employ depending on your servers configuration, your level of access, or for other reasons.

Alternative Setup involves keeping the Zend Framework download together as is, and creating a link from a PATH location to the zf.sh. What this means is you can place the contents of the ZendFramework download into a location such as /usr/local/share/ZendFramework, or more locally like /home/username/lib/ZendFramework, and creating a symbolic link to the zf.sh.

Assuming you want to put the link inside /usr/local/bin (this could also work for placing the link inside /home/username/bin/ for example) you would issue a command similar to this:

  1. ln -s /usr/local/share/ZendFramework/bin/zf.sh /usr/local/bin/zf
  2.
  3. # OR (for example)
  4. ln -s /home/username/lib/ZendFramework/bin/zf.sh /home/username/bin/zf

This will create a link which you should be able to access globally on the command line.

Setting up the CLI tool on Windows

The most common setup in the Windows Win32 environment, is to copy the zf.bat and zf.php into the same directory as your PHP binary. This can generally be found in one of the following places:

  1. C:\PHP
  2. C:\Program Files\ZendServer\bin\
  3. C:\WAMP\PHP\bin

You should be able to run php.exe on the command line. If you are not able to, first check the documentation that came with your PHP distribution, or ensure that the path to php.exe is in your Windows PATH environment variable.

The next order of business is to ensure that Zend Framework library is set up correctly inside of the system PHP include_path. To find out where your include_path is located, you can type php -i and look for the include_path variable, or more succinctly execute php -i | grep include_path if you have Cygwin setup with grep available. Once you have found where your include_path is located (this will generally be something like C:\PHP\pear, C:\PHP\share, C:\Program%20Files\ZendServer\share or similar), ensure that the contents of the library/ directory are put inside your include_path specified directory.

Once you have done those two things, you should be able to issue a command and get back the proper response like this:

< class="inlinemediaobject">

If you do not see this type of output, go back and check your setup to ensure you have all of the necessary pieces in the proper place.

There are a couple of alternative setups you might want to employ depending on your server's configuration, your level of access, or for other reasons.

Alternative Setup involves keeping the Zend Framework download together as is, and altering both your system PATH as well as the php.ini file. In your user's environment, make sure to add C:\Path\To\ZendFramework\bin, so that your zf.bat file is executable. Also, alter the php.ini file to ensure that C:\Path\To\ZendFramework\library is in your include_path.

Other Setup Considerations

If for some reason you do not want Zend Framework library inside your include_path, there is another option. There are two special environment variables that zf.php will utilize to determine the location of your Zend Framework installation.

The first is ZEND_TOOL_INCLUDE_PATH_PREPEND, which will prepend the value of this environment variable to the system (php.ini) include_path before loading the client.

Alternatively, you might want to use ZEND_TOOL_INCLUDE_PATH to completely replace the system include_path for one that makes sense specifically for the zf command line tool.

Where To Go Next?

At this point, you should be set up to start initiating some more "interesting" commands. To get going, you can issue the zf --help command to see what is available to you.

< class="inlinemediaobject">

Continue on to the Zend_Tool_Project "Create Project" section to understand how to use the zf script for project creation.

Introduction
Zend_Tool_Framework
Zend Framework手册 中文版
Architecture
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Tool_Framework
  • Introduction
  • Using the CLI Tool
  • Architecture
  • Creating Providers to use with Zend_Tool_Framework
  • Shipped System Providers
  • Extending and Configuring Zend_Tool_Framework


Architecture - Zend Framework Manual

Using the CLI Tool
Zend_Tool_Framework
Zend Framework手册 中文版
Creating Providers to use with Zend_Tool_Framework

Architecture

Registry

Because providers and manifests may come from anywhere in the include_path, a registry is provided to simplify access to the various pieces of the toolchain. This registry is injected into registry-aware components, which may then pull dependencies from them as necessary. Most dependencies registered with the registry will be sub-component-specific repositories.

The interface for the registry consists of the following definition:

  1. interface Zend_Tool_Framework_Registry_Interface
  2. {
  3.     public function setClient(Zend_Tool_Framework_Client_Abstract $client);
  4.     public function getClient();
  5.     public function setLoader(Zend_Tool_Framework_Loader_Abstract $loader);
  6.     public function getLoader();
  7.     public function setActionRepository(
  8.         Zend_Tool_Framework_Action_Repository $actionRepository
  9.     );
  10.     public function getActionRepository();
  11.     public function setProviderRepository(
  12.         Zend_Tool_Framework_Provider_Repository $providerRepository
  13.     );
  14.     public function getProviderRepository();
  15.     public function setManifestRepository(
  16.         Zend_Tool_Framework_Manifest_Repository $manifestRepository
  17.     );
  18.     public function getManifestRepository();
  19.     public function setRequest(Zend_Tool_Framework_Client_Request $request);
  20.     public function getRequest();
  21.     public function setResponse(Zend_Tool_Framework_Client_Response $response);
  22.     public function getResponse();
  23. }

The various objects the registry manages will be discussed in their appropriate sections.

Classes that should be registry-aware should implement Zend_Tool_Framework_Registry_EnabledInterface. This interface merely allows initialization of the registry in the target class.

  1. interface Zend_Tool_Framework_Registry_EnabledInterface
  2. {
  3.     public function setRegistry(
  4.         Zend_Tool_Framework_Registry_Interface $registry
  5.     );
  6. }

Providers

Zend_Tool_Framework_Provider represents the functional or "capability" aspect of the framework. Fundamentally, Zend_Tool_Framework_Provider will provide the interfaces necessary to produce "providers", or bits of tooling functionality that can be called and used inside the Zend_Tool_Framework toolchain. The simplistic nature of implementing this provider interface allows the developer a "one-stop-shop" of adding functionality or capabilities to Zend_Tool_Framework.

The provider interface is an empty interface and enforces no methods (this is the Marker Interface pattern):

  1. interface Zend_Tool_Framework_Provider_Interface
  2. {}

Or, if you wish, you can implement the base (or abstract) Provider which will give you access to the Zend_Tool_Framework_Registry:

  1. abstract class Zend_Tool_Framework_Provider_Abstract
  2.     implements Zend_Tool_Framework_Provider_Interface,
  3.                Zend_Tool_Registry_EnabledInterface
  4. {
  5.     protected $_registry;
  6.     public function setRegistry(
  7.         Zend_Tool_Framework_Registry_Interface $registry
  8.     );
  9. }

Loaders

The purpose of a Loader is to find Providers and Manifest files that contain classes which implement either Zend_Tool_Framework_Provider_Interface or Zend_Tool_Framework_Manifest_Interface. Once these files are found by a loader, providers are loaded into the Provider Repository and manifest metadata is loaded into the Manifest Repository.

To implement a loader, one must extend the following abstract class:

  1. abstract class Zend_Tool_Framework_Loader_Abstract
  2. {
  3.
  4.     abstract protected function _getFiles();
  5.
  6.     public function load()
  7.     {
  8.         /** ... */
  9.     }
  10. }

The _getFiles() method should return an array of files (absolute paths). The built-in loader supplied with Zend Framework is called the IncludePath loader. By default, the Tooling framework will use an include_path based loader to find files that might include Providers or Manifest Metadata objects. Zend_Tool_Framework_Loader_IncludePathLoader, without any other options, will search for files inside the include path that end in Mainfest.php, Tool.php or Provider.php. Once found, they will be tested (by the load() method of the Zend_Tool_Framework_Loader_Abstract) to determine if they implement any of the supported interfaces. If they do, an instance of the found class is instantiated, and it is appended to the proper repository.

  1. class Zend_Tool_Framework_Loader_IncludePathLoader
  2.     extends Zend_Tool_Framework_Loader_Abstract
  3. {
  4.
  5.     protected $_filterDenyDirectoryPattern = '.*(/|\\\\).svn';
  6.     protected $_filterAcceptFilePattern = '.*(?:Manifest|Provider)\.php$';
  7.
  8.     protected function _getFiles()
  9.     {
  10.         /** ... */
  11.     }
  12. }

As you can see, the IncludePath loader will search all include_paths for the files that match the $_filterAcceptFilePattern and not match the $_filterDenyDirectoryPattern.

Manifests

In short, the Manifest shall contain specific or arbitrary metadata that is useful to any provider or client, as well as be responsible for loading any additional providers into the provider repository.

To introduce metadata into the manifest repository, all one must do is implement the empty Zend_Tool_Framework_Manifest_Interface, and provide a getMetadata() method which shall return an array of objects that implement Zend_Tool_Framework_Manifest_Metadata.

  1. interface Zend_Tool_Framework_Manifest_Interface
  2. {
  3.     public function getMetadata();
  4. }

Metadata objects are loaded (by a loader defined below) into the Manifest Repository (Zend_Tool_Framework_Manifest_Repository). Manifests will be processed after all Providers have been found to be loaded into the provider repository. This shall allow Manifests to create Metadata objects based on what is currently inside the provider repository.

There are a few different metadata classes that can be used to describe metadata. The Zend_Tool_Framework_Manifest_Metadata is the base metadata object. As you can see by the following code snippet, the base metadata class is fairly lightweight and abstract in nature:

  1. class Zend_Tool_Framework_Metadata_Basic
  2. {
  3.
  4.     protected $_type        = 'Global';
  5.     protected $_name        = null;
  6.     protected $_value       = null;
  7.     protected $_reference   = null;
  8.
  9.     public function getType();
  10.     public function getName();
  11.     public function getValue();
  12.     public function getReference();
  13.     /** ... */
  14. }

There are other built in metadata classes as well for describing more specialized metadata: ActionMetadata and ProviderMetadata. These classes will help you describe in more detail metadata that is specific to either actions or providers, and the reference is expected to be a reference to an action or a provider respectively. These classes are described in the following code snippet.

  1. class Zend_Tool_Framework_Manifest_ActionMetadata
  2.     extends Zend_Tool_Framework_Manifest_Metadata
  3. {
  4.
  5.     protected $_type = 'Action';
  6.     protected $_actionName = null;
  7.
  8.     public function getActionName();
  9.     /** ... */
  10. }
  11.
  12. class Zend_Tool_Framework_Manifest_ProviderMetadata
  13.     extends Zend_Tool_Framework_Manifest_Metadata
  14. {
  15.
  16.     protected $_type = 'Provider';
  17.     protected $_providerName  = null;
  18.     protected $_actionName    = null;
  19.     protected $_specialtyName = null;
  20.
  21.     public function getProviderName();
  22.     public function getActionName();
  23.     public function getSpecialtyName();
  24.     /** ... */
  25. }

'Type' in these classes is used to describe the type of metadata the object is responsible for. In the cases of the ActionMetadata, the type would be 'Action', and conversely in the case of the ProviderMetadata the type is 'Provider'. These metadata types will also include additional structured information about both the "thing" they are describing as well as the object (the getReference()) they are referencing with this new metadata.

In order to create your own metadata type, all one must do is extend the base Zend_Tool_Framework_Manifest_Metadata class and return these new metadata objects via a local Manifest class or object. These user based classes will live in the Manifest Repository

Once these metadata objects are in the repository, there are then two different methods that can be used in order to search for them in the repository.

  1. class Zend_Tool_Framework_Manifest_Repository
  2. {
  3.     /**
  4.      * To use this method to search, $searchProperties should contain the names
  5.      * and values of the key/value pairs you would like to match within the
  6.      * manifest.
  7.      *
  8.      * For Example:
  9.      *     $manifestRepository->findMetadatas(array(
  10.      *         'action' => 'Foo',
  11.      *         'name'   => 'cliActionName'
  12.      *         ));
  13.      *
  14.      * Will find any metadata objects that have a key with name 'action' value
  15.      * of 'Foo', AND a key named 'name' value of 'cliActionName'
  16.      *
  17.      * Note: to either exclude or include name/value pairs that exist in the
  18.      * search criteria but do not appear in the object, pass a bool value to
  19.      * $includeNonExistentProperties
  20.      */
  21.     public function findMetadatas(Array $searchProperties = array(),
  22.                                   $includeNonExistentProperties = true);
  23.
  24.     /**
  25.      * The following will return exactly one of the matching search criteria,
  26.      * regardless of how many have been returned. First one in the manifest is
  27.      * what will be returned.
  28.      */
  29.     public function findMetadata(Array $searchProperties = array(),
  30.                                  $includeNonExistentProperties = true)
  31.     {
  32.         $metadatas = $this->getMetadatas($searchProperties,
  33.                                          $includeNonExistentProperties);
  34.         return array_shift($metadatas);
  35.     }
  36. }

Looking at the search methods above, the signatures allow for extremely flexible searching. In order to find a metadata object, simply pass in an array of matching constraints via an array. If the data is accessible through the Property accessor (the getSomething() methods implemented on the metadata object), then it will be passed back to the user as a "found" metadata object.

Clients

Clients are the interface which bridges a user or external tool into the Zend_Tool_Framework system. Clients can come in all shapes and sizes: RPC endpoints, Command Line Interface, or even a web interface. Zend_Tool has implemented the command line interface as the default interface for interacting with the Zend_Tool_Framework system.

To implement a client, one would need to extend the following abstract class:

  1. abstract class Zend_Tool_Framework_Client_Abstract
  2. {
  3.     /**
  4.      * This method should be implemented by the client implementation to
  5.      * construct and set custom loaders, request and response objects.
  6.      *
  7.      * (not required, but suggested)
  8.      */
  9.     protected function _preInit();
  10.
  11.     /**
  12.      * This method should be implemented by the client implementation to parse
  13.      * out and set up the request objects action, provider and parameter
  14.      * information.
  15.      */
  16.     abstract protected function _preDispatch();
  17.
  18.     /**
  19.      * This method should be implemented by the client implementation to take
  20.      * the output of the response object and return it (in an client specific
  21.      * way) back to the Tooling Client.
  22.      *
  23.      * (not required, but suggested)
  24.      */
  25.     abstract protected function _postDispatch();
  26. }

As you can see, there 1 method is required to fulfill the needs of a client (two others suggested), the initialization, prehandling and post handling. For a more in depth study of how the command line client works, please see the » source code.

Using the CLI Tool
Zend_Tool_Framework
Zend Framework手册 中文版
Creating Providers to use with Zend_Tool_Framework
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Tool_Framework
  • Introduction
  • Using the CLI Tool
  • Architecture
  • Creating Providers to use with Zend_Tool_Framework
  • Shipped System Providers
  • Extending and Configuring Zend_Tool_Framework


Creating Providers to use with Zend_Tool_Framework - Zend Framework Manual

Architecture
Zend_Tool_Framework
Zend Framework手册 中文版
Shipped System Providers

Creating Providers to use with Zend_Tool_Framework

In general, a provider, on its own, is nothing more than the shell for a developer to bundle up some capabilities they wish to dispatch with the command line (or other) clients. It is an analogue to what a "controller" is inside of your MVC application.

How Zend Tool finds your Providers

By default Zend Tool uses the IncludePathLoader to find all the providers that you can run. It recursivly iterates all include path directories and opens all files that end with "Manifest.php" or "Provider.php". All classes in these files are inspected if they implement either Zend_Tool_Framework_Provider_Interface or Zend_Tool_Framework_Manifest_ProviderManifestable. Instances of the provider interface make up for the real functionality and all their public methods are accessible as provider actions. The ProviderManifestable interface however requires the implementation of a method getProviders() which returns an array of instantiated provider interface instances.

The following naming rules apply on how you can access the providers that were found by the IncludePathLoader:

  • The last part of your classname split by underscore is used for the provider name, e.g. "My_Provider_Hello" leads to your provider being accessible by the name "hello".

  • If your provider has a method getName() it will be used instead of the previous method to determine the name.

  • If your provider has "Provider" as prefix, e.g. it is called My_HelloProvider it will be stripped from the name so that the provider will be called "hello".

Note: The IncludePathLoader does not follow symlinks, that means you cannot link provider functionality into your include paths, they have to be physically present in the include paths.

Example #1 Exposing Your Providers with a Manifest

You can expose your providers to Zend Tool by offering a manifest with a special filename ending with "Manifest.php". A Provider Manifest is an implementation of the Zend_Tool_Framework_Manifest_ProviderManifestable and requires the getProviders() method to return an array of instantiated providers. In anticipation of our first own provider My_Component_HelloProvider we will create the following manifest:

  1. class My_Component_Manifest
  2.     implements Zend_Tool_Framework_Manifest_ProviderManifestable
  3. {
  4.     public function getProviders()
  5.     {
  6.         return array(
  7.             new My_Component_HelloProvider()
  8.         );
  9.     }
  10. }

Basic Instructions for Creating Providers

As an example, if a developer wants to add the capability of showing the version of a datafile that his 3rd party component is working from, there is only one class the developer would need to implement. Assuming the component is called My_Component, he would create a class named My_Component_HelloProvider in a file named HelloProvider.php somewhere on the include_path. This class would implement Zend_Tool_Framework_Provider_Interface, and the body of this file would only have to look like the following:

  1. class My_Component_HelloProvider
  2.     implements Zend_Tool_Framework_Provider_Interface
  3. {
  4.     public function say()
  5.     {
  6.         echo 'Hello from my provider!';
  7.     }
  8. }

Given that code above, and assuming the developer wishes to access this functionality through the console client, the call would look like this:

  1. % zf say hello
  2. Hello from my provider!

The response object

As discussed in the architecture section Zend Tool allows to hook different clients for using your Zend Tool providers. To keep compliant with different clients you should use the response object to return messages from your providers instead of using echo() or a similiar output mechanism. Rewritting our hello provider with this knowledge it looks like:

  1. class My_Component_HelloProvider
  2.     extends Zend_Tool_Framework_Provider_Abstract
  3. {
  4.     public function say()
  5.     {
  6.         $this->_registry->getResponse
  7.                         ->appendContent("Hello from my provider!");
  8.     }
  9. }

As you can see one has to extend the Zend_Tool_Framework_Provider_Abstract to gain access to the Registry which holds the Zend_Tool_Framework_Client_Response instance.

Advanced Development Information

Passing Variables to a Provider

The above "Hello World" example is great for simple commands, but what about something more advanced? As your scripting and tooling needs grow, you might find that you need the ability to accept variables. Much like function signatures have parameters, your tooling requests can also accept parameters.

Just as each tooling request can be isolated to a method within a class, the parameters of a tooling request can also be isolated in a very well known place. Parameters of the action methods of a provider can include the same parameters you want your client to utilize when calling that provider and action combination. For example, if you wanted to accept a name in the above example, you would probably do this in OO code:

  1. class My_Component_HelloProvider
  2.     implements Zend_Tool_Framework_Provider_Interface
  3. {
  4.     public function say($name = 'Ralph')
  5.     {
  6.         echo 'Hello' . $name . ', from my provider!';
  7.     }
  8. }

The above example can then be called via the command line zf say hello Joe. "Joe" will be supplied to the provider as a parameter of the method call. Also note, as you see that the parameter is optional, that means it is also optional on the command line, so that zf say hello will still work, and default to the name "Ralph".

Prompt the User for Input

There are cases when the workflow of your provider requires to prompt the user for input. This can be done by requesting the client to ask for more the required input by calling:

  1. class My_Component_HelloProvider
  2.     extends Zend_Tool_Framework_Provider_Abstract
  3. {
  4.     public function say($name = 'Ralph')
  5.     {
  6.         $nameResponse = $this->_registry
  7.                              ->getClient()
  8.                              ->promptInteractiveInput("Whats your name?");
  9.         $name = $name->getContent();
  10.
  11.         echo 'Hello' . $name . ', from my provider!';
  12.     }
  13. }

This command throws an exception if the current client is not able to handle interactive requests. In case of the default Console Client however you will be asked to enter the name.

Pretending to execute a Provider Action

Another interesting feature you might wish to implement is pretendability. Pretendabilty is the ability for your provider to "pretend" as if it is doing the requested action and provider combination and give the user as much information about what it would do without actually doing it. This might be an important notion when doing heavy database or filesystem modifications that the user might not otherwise want to do.

Pretendability is easy to implement. There are two parts to this feature: 1) marking the provider as having the ability to "pretend", and 2) checking the request to ensure the current request was indeed asked to be "pretended". This feature is demonstrated in the code sample below.

  1. class My_Component_HelloProvider
  2.     extends    Zend_Tool_Framework_Provider_Abstract
  3.     implements Zend_Tool_Framework_Provider_Pretendable
  4. {
  5.     public function say($name = 'Ralph')
  6.     {
  7.         if ($this->_registry->getRequest()->isPretend()) {
  8.             echo 'I would say hello to ' . $name . '.';
  9.         } else {
  10.             echo 'Hello' . $name . ', from my provider!';
  11.         }
  12.     }
  13. }

To run the provider in pretend mode just call:

  1. % zf --pretend say hello Ralph
  2. I would say hello Ralph.

Verbose and Debug modes

You can also run your provider actions in "verbose" or "debug" modes. The semantics in regard to this actions have to be implemented by you in the context of your provider. You can access debug or verbose modes with:

  1. class My_Component_HelloProvider
  2.     implements Zend_Tool_Framework_Provider_Interface
  3. {
  4.     public function say($name = 'Ralph')
  5.     {
  6.         if($this->_registry->getRequest()->isVerbose()) {
  7.             echo "Hello::say has been called\n";
  8.         }
  9.         if($this->_registry->getRequest()->isDebug()) {
  10.             syslog(LOG_INFO, "Hello::say has been called\n");
  11.         }
  12.     }
  13. }

Accessing User Config and Storage

Using the Enviroment variable ZF_CONFIG_FILE or the .zf.ini in your home directory you can inject configuration parameters into any Zend Tool provider. Access to this configuration is available via the registry that is passed to your provider if you extend Zend_Tool_Framework_Provider_Abstract.

  1. class My_Component_HelloProvider
  2.     extends Zend_Tool_Framework_Provider_Abstract
  3. {
  4.     public function say()
  5.     {
  6.         $username = $this->_registry->getConfig()->username;
  7.         if(!empty($username)) {
  8.             echo "Hello $username!";
  9.         } else {
  10.             echo "Hello!";
  11.         }
  12.     }
  13. }

The returned configuration is of the type Zend_Tool_Framework_Client_Config but internally the __get() and __set() magic methods proxy to a Zend_Config of the given configuration type.

The storage allows to save arbitrary data for later reference. This can be useful for batch processing tasks or for re-runs of your tasks. You can access the storage in a similar way like the configuration:

  1. class My_Component_HelloProvider
  2.     extends Zend_Tool_Framework_Provider_Abstract
  3. {
  4.     public function say()
  5.     {
  6.         $aValue = $this->_registry->getStorage()->get("myUsername");
  7.         echo "Hello $aValue!";
  8.     }
  9. }

The API of the storage is very simple:

  1. class Zend_Tool_Framework_Client_Storage
  2. {
  3.     public function setAdapter($adapter);
  4.     public function isEnabled();
  5.     public function put($name, $value);
  6.     public function get($name, $defaultValue=null);
  7.     public function has($name);
  8.     public function remove($name);
  9.     public function getStreamUri($name);
  10. }
Important

When designing your providers that are config or storage aware remember to check if the required user-config or storage keys really exist for a user. You won't run into fatal errors when none of these are provided though, since empty ones are created upon request.

Architecture
Zend_Tool_Framework
Zend Framework手册 中文版
Shipped System Providers
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Tool_Framework
  • Introduction
  • Using the CLI Tool
  • Architecture
  • Creating Providers to use with Zend_Tool_Framework
  • Shipped System Providers
  • Extending and Configuring Zend_Tool_Framework


Shipped System Providers - Zend Framework Manual

Creating Providers to use with Zend_Tool_Framework
Zend_Tool_Framework
Zend Framework手册 中文版
Extending and Configuring Zend_Tool_Framework

Shipped System Providers

In addition to the more useful project based providers that come shipped with Zend_Tool_Project, there are also some more basic, but interesting providers that come built into Zend_Tool_Framework. Some of these exist for the purpose of providing a means via the command line to extract information, such as the version, while others are intended to aid the developer when creating additional providers.

The Version Provider

The Version provider is included so that you may determine which version of the framework that the zf or Zend_Tool is currently set to work with.

Through the command line, simply run zf show version.

The Manifest Provider

The Manifest provider is included so that you may determine what kind of "manifest" information is available during the Zend_Tool runtime. Manifest data is information that is attached to specific objects during Zend_Tool's runtime. Inside the manifest you will find the console specific namings that you are expected to use when calling certain commands. Data found in the manifest can be used by any provider or client on an as-needed basis.

Through the command line, simply run zf show manifest.

Creating Providers to use with Zend_Tool_Framework
Zend_Tool_Framework
Zend Framework手册 中文版
Extending and Configuring Zend_Tool_Framework
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Tool_Framework
  • Introduction
  • Using the CLI Tool
  • Architecture
  • Creating Providers to use with Zend_Tool_Framework
  • Shipped System Providers
  • Extending and Configuring Zend_Tool_Framework


Extending and Configuring Zend_Tool_Framework - Zend Framework Manual

Shipped System Providers
Zend_Tool_Framework
Zend Framework手册 中文版
Zend_Tool_Project

Extending and Configuring Zend_Tool_Framework

Customizing Zend_Tool Console Client

As of Zend Framework 1.9, Zend_Tool_Framework allows developers to store information, provider specific configuration values, and custom files in a special location on the developers machine. These configuration values and files can be used by providers to extend functionality, customize functionality, or any other reasons a provider sees fit.

The primary purpose, and the purpose most immediately used by existing providers is to allow developers to customize the way the "out of the box" providers do work.

One of the more commonly requested features is to be able to provide custom project profiles to Zend_Tool_Project's Project Provider. This would allow developers to store a custom profile in a special place that can be used repeatedly by the Zend_Tool system in order to build custom profiles. Another commonly requested feature is to be able to configure the behavior of providers with a configuration setting. In order to achieve this, not only do we have to have a Zend_Tool configuration file, but we also have to have a place to find this configuration file.

The Home Directory

Before the Console Client can start searching for a Zend_Tool configuration file or a local storage directory, it must first be able to identify where the "home directory" is located.

On *nix-based machines, PHP will be populated with an environment variable named HOME with a path to the current users home directory. Typically, this path will be very similar to /home/myusername.

On Windows-based machines, PHP will typically be populated with an environment variable named HOMEPATH with the current users home directory. This directory is usually found in either C:\Documents and Settings\Username\, or in Vista at C:\Users\Username.

If either a home directory cannot be found, or you wish to change the location of where Zend_Tool_Framework Console Client finds the home directory, you can provide an environment variable named ZF_HOME to specify where to find the home directory.

Local Storage

Once a home directory can be located, Zend_Tool_Framework's Console Client can either autodiscover the local storage directory, or it can be told where to expect the local storage directory.

Assuming the home directory has been found (here noted as $HOME), the Console Client will then look for the local storage directory in $HOME/.zf/. If found, it will set the local storage directory to this location.

If the directory cannot be found, or the developer wishes to override this location, that can be done by setting an environment variable. Regardless if $HOME has been previously set or not, the developer may supply the environment variable ZF_STORAGE_DIR.

Once the path to a local storage directory is found, the directory must exist for it to be passed into the Zend_Tool_Framework runtime, as it will not be created for you.

User Configuration

Like local storage, once a home directory can be located, Zend_Tool_Framework's Console Client can then either attempt to autodiscover the path to a configuration file, or it can be told specifically where to find the configuration file.

Assuming the home directory has been found (here noted as $HOME), the Console Client will then attempt to look for the existence of a configuration file located at $HOME/.zf.ini. This file, if found, will be used as the configuration file for Zend_Tool_Framework.

If that location does not exist, but a local storage directory does, then the Console Client will then attempt to locate the configuration file within the local storage directory. Assuming the local storage directory exists in $LOCAL_STORAGE, then if a file exists as $LOCAL_STORAGE/zf.ini, it will be found by the Console Client and utilized as the Zend_Tool_Framework configuration file.

If the file cannot be autodiscovered or the developer wishes to specify the location of location of the configuration file, the developer can do so by setting an environment variable. If the environment variable ZF_CONFIG_FILE is set, then its value will be used as the location of the configuration file to use with the Console Client. The ZF_CONFIG_FILE can point to any Zend_Config readable INI, XML or PHP File.

If the file does not exist in either the autodiscovered or the provided location, it will not be used as Zend_Tool_Framework does not attempt to create the file automatically.

User Configuration File Content

The configuration file should be structured as a Zend_Config configuration file, in ini format, and without any sections being defined. First level keys should be used by the provider searching for a specific value. For example, if the "Project" provider is expecting a "profiles" directory, then it should typically be understood that it will search for the following ini key value pair:

  1. project.profile = some/path/to/some-directory

The only reserved ini prefix is the value "php". The "php" prefix to values will be reserved to store names and values of runtime settable php values, such as include_path or error_reporting. To override the include_path and error_reporting with an ini value, a developer would set:

  1. php.include_path = "/path/to/includes1:/path/to/includes2"
  2. php.error_reporting = 1
Important

The reserved prefix "php" only works with INI files. You can't set PHP INI values with PHP or XML config.

Shipped System Providers
Zend_Tool_Framework
Zend Framework手册 中文版
Zend_Tool_Project
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Tool_Framework
  • Introduction
  • Using the CLI Tool
  • Architecture
  • Creating Providers to use with Zend_Tool_Framework
  • Shipped System Providers
  • Extending and Configuring Zend_Tool_Framework


Zend_Tool_Project - Zend Framework Manual

Extending and Configuring Zend_Tool_Framework
Zend Framework Reference
Zend Framework手册 中文版
Introduction

Zend_Tool_Project

Table of Contents
  • Introduction
  • Create A Project
  • Zend Tool Project Providers
  • Zend_Tool_Project 内部机制
Extending and Configuring Zend_Tool_Framework
Zend Framework Reference
Zend Framework手册 中文版
Introduction
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


Introduction - Zend Framework Manual

Zend_Tool_Project
Zend_Tool_Project
Zend Framework手册 中文版
Create A Project

Introduction

Zend_Tool_Project builds on and extends the capabilities of Zend_Tool_Framework to that of managing a "project". In general, a "project" is a planned endeavor or an initiative. In the computer world, projects generally are a collection of resources. These resources can be files, directories, databases, schemas, images, styles, and more.

This same concept applies to Zend Framework projects. In Zend Framework projects, you have controllers, actions, views, models, databases and so on and so forth. In terms of Zend_Tool, we need a way to track these types of resources - thus Zend_Tool_Project.

Zend_Tool_Project is capable of tracking project resources throughout the development of a project. So, for example, if in one command you created a controller, and in the next command you wish to create an action within that controller, Zend_Tool_Project is gonna have to know about the controller file you created so that you can (in the next action), be able to append that action to it. This is what keeps our projects up to date and stateful.

Another important point to understand about projects is that typically, resources are organized in a hierarchical fashion. With that in mind, Zend_Tool_Project is capable of serializing the current project into a internal representation that allows it to keep track of not only what resources are part of a project at any given time, but also where they are in relation to one another.

Zend_Tool_Project
Zend_Tool_Project
Zend Framework手册 中文版
Create A Project
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Tool_Project
  • Introduction
  • Create A Project
  • Zend Tool Project Providers
  • Zend_Tool_Project 内部机制


Create A Project - Zend Framework Manual

Introduction
Zend_Tool_Project
Zend Framework手册 中文版
Zend Tool Project Providers

Create A Project

Note: The following examples will assume you have the command line interface of Zend_Tool_Framework available to you.

Note: To issue any of the commands for Zend_Tool_Project with CLI, you must be in the directory where the project was initially created.

To get started with Zend_Tool_Project, you simply need to create a project. Creating a project is simple: go to a place on your filesystem, create a directory, change to that directory, then issue the following command:

/tmp/project$ zf create project

Optionally, you can create a directory anywhere by the following:

$ zf create project /path/to/non-existent-dir

The following table will describe the capabilities of providers that are available to you. As you can see in this table, there is a "Project" provider. The Project provider has a couple of actions associated to it, and with those actions a number of options that can be used to modify the behavior of the action and provider.

Project Provider Options
Provider Name | Available Actions | Parameters | CLI Usage
Project | Create / Show | create - [path=null, profile='default'] | zf create project some/path
Introduction
Zend_Tool_Project
Zend Framework手册 中文版
Zend Tool Project Providers
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Tool_Project
  • Introduction
  • Create A Project
  • Zend Tool Project Providers
  • Zend_Tool_Project 内部机制


Zend Tool Project Providers - Zend Framework Manual

Create A Project
Zend_Tool_Project
Zend Framework手册 中文版
Zend_Tool_Project 内部机制

Zend Tool Project Providers

Below is a table of all of the providers shipped with Zend_Tool_Project.

Project Provider Options
Provider Name | Available Actions | Parameters | CLI Usage
Controller | Create | create - [name, indexActionIncluded=true] | zf create controller foo
Action | Create | create - [name, controllerName=index, viewIncluded=true] | zf create action bar foo (or zf create action --name bar --controlller-name=foo)
Controller | Create | create - [name, indexActionIncluded=true] | zf create controller foo
Profile | Show | show - [] | zf show profile
View | Create | create - [controllerName,actionNameOrSimpleName] | zf create view foo bar (or zf create view -c foo -a bar)
Test | Create / Enable / Disable | create - [libraryClassName] | zf create test My_Foo_Baz / zf disable test / zf enable test
Create A Project
Zend_Tool_Project
Zend Framework手册 中文版
Zend_Tool_Project 内部机制
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Tool_Project
  • Introduction
  • Create A Project
  • Zend Tool Project Providers
  • Zend_Tool_Project 内部机制


Zend_Tool_Project 内部机制 - Zend Framework Manual

Zend Tool Project Providers
Zend_Tool_Project
Zend Framework手册 中文版
Zend_Translate

Zend_Tool_Project 内部机制

Zend_Tool_Project 内部 Xml 结构

Zend_Tool_Project 内部扩展

Zend Tool Project Providers
Zend_Tool_Project
Zend Framework手册 中文版
Zend_Translate
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Tool_Project
  • Introduction
  • Create A Project
  • Zend Tool Project Providers
  • Zend_Tool_Project 内部机制


Zend_Translate - Zend Framework Manual

Zend_Tool_Project 内部机制
Zend Framework Reference
Zend Framework手册 中文版
简介

Zend_Translate

Table of Contents
  • 简介
  • Zend_Translate适配器
  • Using Translation Adapters
  • Creating source files
  • Additional features for translation
  • Plural notations for Translation
Zend_Tool_Project 内部机制
Zend Framework Reference
Zend Framework手册 中文版
简介
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


简介 - Zend Framework Manual

Zend_Translate
Zend_Translate
Zend Framework手册 中文版
Zend_Translate适配器

简介

Zend_Translate是Zend框架为多语言应用程序提供的一个解决方案.

在多语言应用程序中,内容必须翻译为多种语言,并且根据用户的语言设置显示相应的内容. PHP已经提供了几个方法处理这样的问题,但是存在一些问题:

  • 不一致的API: 对于不同的源格式没有单一的API.gettext的使用非常复杂.

  • PHP仅支持gettext和原生数组: PHP本生仅为数组和gettext提供支持 . 所有其他的源格式必须自己进行处理,因为没有提供原生的支持.

  • 不检测默认语言: 没有深入的不同浏览器的背景知识,用户的默认语言不能被检测.

  • Gettext 是非线程安全的: PHP'的gettext库不是现在安全的,并且它不应该用于多线程环境中.这是由于gettex本生的问题而不是PHP,但却是一个存在的问题.

Zend_Translate没有上面的问题.这就是为什么我们推进使用Zend_Translate而不是PHP的原生函数.Zend_Translate的优点有:

  • 支持多种源格式: Zend_Translate 支持多种源格式, 包括被PHP支持的,和其他的格式,包括TMX和CSV文件.

  • 线程安全的gettext: Zend_Translate 的 gettext reader是线程安全的.在多线程的环境中使用它没有问题.

  • 简易并且通用的API: Zend_Translate的API非常简单并且只要求少数的函数.因此易于学习和维护.所有的源格式用同样的方法处理,如果你的源格式从Gettext改为TMX, 你只需要改变一行代码指定存储适配器.

  • 用户的标准语言检测: 用户访问站点的首选语言能够通过被检测并被Zend_Translate使用。

  • 自动源文检测： Zend_Translate 能够检测和集成多个源文件并根据文件名或目录另外地检测哪个地方（locale）在用。

开始多语言化

让我们打开多语言Web应用程序的窗口.我们想做的是转换字符串,产生翻译后的输出. 否则我们不得不给每种语言都写一个视图,没人愿意这么做.通常,多语言站点在设计中是非常简单的.仅有4个必须做的步骤:

  1. 决定你想使用那个适配器;

  2. 创建视图并把Zend_Translate集成到你的代码中.

  3. 从你的代码中创建源文件;

  4. 翻译你的源文件为所期望的语言.

下面的章节将指导你通过全部4个步骤.读取接下来的一些页面创建你自己的多语言web应用程序.

Zend_Translate
Zend_Translate
Zend Framework手册 中文版
Zend_Translate适配器
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Translate
  • 简介
  • Zend_Translate适配器
  • Using Translation Adapters
  • Creating source files
  • Additional features for translation
  • Plural notations for Translation


Zend_Translate适配器 - Zend Framework Manual

简介
Zend_Translate
Zend Framework手册 中文版
Using Translation Adapters

Zend_Translate适配器

Zend_Translate能够处理不同的翻译适配器，每种适配器有它自己的优点和缺点，下面是一个完整的适配器支持列表。

Zend_Translate适配器
适配器 | 描述 | Usage
Array | 使用PHP数组 | 小页面;使用最简单;仅对程序员
Csv | 使用逗号分隔值(*.csv/*.txt)文件 | 简单的文本文件格式;非常快; 可能有unicode字符的问题
Gettext | 使用二进制gettext (*.mo)文件 | Linux GNU标准;非常快;线程安全;需要工具进行转换
Ini | 使用简单的 ini (*.ini) 文件 | 简单文本文件格式；非常块；可能有 unicode 字符问题
Tbx | 使用基于术语交换 (*.tbx/*.xml) 文件 | 程序间术语字符串工业标准；XML 格式
Tmx | 使用 tmx (*.tmx/*.xml) 文件 | 程序间转化工业标准;XML格式;人可读
Qt | Use qt linguist (*.ts) files | 跨平台程序框架；XML 格式；人可读
Xliff | 使用 xliff (*.xliff/*.xml) 文件 | 一个比TMX更加简单的格式;XML格式;人可读
XmlTm | 使用 xmltm (*.xml) 文件 | XML 文档转换内存工业标准；XML 格式；人可读
其他 | *.sql | 与其他适配器不同,可能在将来实现

如何判断使用哪种翻译适配器

你应该决定对Zend_Translate使用哪种适配器，常常，外部条件,例如一个项目需求或者客户需求为你决定了使用哪种适配器，但是入你站在决策的位置,下面的提示可能有对你的决定帮助。

Note: 决定适配器的时候，应当知道编码的使用。即便 Zend Framework 声明 UTF-8 为缺省编码，你有时候也需要其它编码。 Zend_Translate 不改变任何定义在源文件种的编码，意味着如果你的 Gettext 源建立在 ISO-8859-1 之上，它也俺此编码返回字符串而不需要转换。 只有一个唯一的限制：
当使用基于 xml 源格式如 TMX 或 XLIFF，你必需在 xml 文件头内定义编码，因为不定义编码，xml 文件将被 xml 解析器缺省地当作 UTF-8。 你也应当知道实际上 xml 文件的编码局限于 PHP 支持的编码是 UTF-8，ISO-8859-1 和 US-ASCII。

Zend_Translate_Adapter_Array

数组适配器对程序员来说是使用最简单的一种适配器，但是如果你有大量的字符串和许多语言要翻译，你应该考虑其他的适配器。例如，如果你有5000个字符串要翻译，数组适配器对你来说并非最好的选择。

你应该仅在小规模站点，不多的语言需要翻译时使用本适配器，要是你或则你的开发者团队创建你们自己的翻译。

Zend_Translate_Adapter_Csv

Csv对于用户是使用上最简单的一种适配器，CSV 文件可以通过标准的文本编辑器读取,但是有些文本编辑器通常不支持utf8字符集。

你应该仅在你的客户需要自己翻译时使用本适配器。

Zend_Translate_Adapter_Gettext

Gettext适配器是最常用的一种适配器。Gettext是一种由GNU引入的翻译源格式，现在在世界上广泛使用，它不是人可读的，但有几个免费的工具（例如 » POEdit），用于读取Gettext数据。Zend_Translate Gettext 适配器并不是使用 PHP 的 gettext 扩展实现的。 你可以在没有安装 PHP 的 gettext 扩展的情况下也能够使用 Gettext 适配器。还有 Zend_Translate 的 Gettext 适配器是线程安全的，而 PHP 的 gettext 扩展当前是非线程安全的。

大多数人使用本适配器，可用的工具，专业的翻译非常简单。但是 gettext 数据存储为机器可读的格式，没有工具，它是不可读的。

Zend_Translate_Adapter_Ini

Ini 适配器非常简单，客户都可以直接使用。INI 文件可以用标准文本编辑器读出，但文本编辑器一般不支持 utf8 字符集。

在客户想自己翻译的情况下你只能用这个适配器，对于一般的翻译源，不要使用它。

Zend_Translate_Adapter_Tbx

Tbx 适配器是给已经为他们的内部翻译系统使用 TBX 格式的客户来使用的。 Tbx 没有标准翻译格式，只是已经翻译的集合和预翻译原文。 当使用这个适配器，你必须确认所需的原文已经翻译。TBX 是基于 XML 文件的格式的全新格式。XML 文件是人类可读的，但是解析的速度却不如 gettext 文件快。

这个适配器对预翻译原文已存在的公司来说很理想，文件是人类可读，并且不依赖操作系统的。

Zend_Translate_Adapter_Tmx

Tmx适配器用于有多个系统,并且那些系统使用同样的源格式的大多数客户,或则翻译源格式必须是不依赖与系统的，TMX 是一种基于 XML 的文件格式,它宣称将成为下一个工业标准， XML 文件是人可读的,但是解析的速度却不如 gettext 文件快。

大多数中到大型的公司使用本适配器，因为文件是人可读的,不依赖于系统。

Zend_Translate_Adapter_Qt

Qt 适配器适用于使用 QtLinguist 生成的 TS 文件作为其翻译源的用户。QT 使用 XML 作为基本文件格式。XML 是用户可读的，但是分析速度比不上 gettext 文件。

许多应用是构建在 QT 框架之上的。 这个格式的文件是人类可读，并且不依赖操作系统。

Zend_Translate_Adapter_Xliff

Xliff适配器被那些想使用XML文件但是没有TMX工具的多数客户使用， XLIFF 也是一种基于XML的文件格式,它是于TMX相关的但是比TMX更简单，他仅支持TMX的部分功能。XML文件是人可读的，但是解析的速度却不如gettext文件快 。

多数中型公司使用此适配器,这个格式的文件是人可读,并且不依赖操作系统。

Zend_Translate_Adapter_XmlTm

XmlTm 适配器为那些做他们自己的布局的客户使用，XmlTm 是允许完全的 html 源包括在翻译源中的文件格式，所以翻译和布局结合在一起。XLIFF 是基于 XML 的文件格式， 和 XLIFF 相关但不容易读。

这个适配器仅用于源文件已经存在，这个格式的文件是人类可读，并且不依赖操作系统。

集成编写自己的适配器

Zend_Translate 允许编写并使用自己的适配器类。并且可以像 Zend_Translate 内置的标准类一样使用。

任何要在 Zend_Translate 使用的适配器都必须继承于 Zend_Translate_Adapter，抽象类 Zend_Translate_Adapter 定义了所有翻译需要的内容。用户需要做的，就是定义如何读取翻译数据（Translation Data）。

前缀“Zend”仅限由 Zend_Framework 使用。如果使用自己的适配器扩展了 Zend_Framework，应当命名为 “Company_Translate_Adapter_MyFormat”。下面的代码演示了如何编写一个自定义适配器：

<?php
require_once 'Zend/Translate.php';

try {
    $translate = new Zend_Translate('Company_Translate_Adapter_MyFormat', '/path/to/translate.xx', 'en', array('myoption' => 'myvalue'));
} catch (Exception $e) {
    // 文件没找到，没有适配器类
    // 通常的错误
}

加速所有的适配器

Zend_Translate 允许内部使用 Zend_Cache 来加速翻译源文件的加载，如果使用很多翻译源文件或很多源文件格式如基于 XML 的文件格式，这非常好使。

为使用缓存，将只需要给 Zend_Translate::setCache() 方法一个缓存对象， 它把 Zend_Cache 的实例做为唯一的参数，并且，如果直接使用任何适配器，你可以使用 setCache() 方法。 静态方法 Zend_Translate::getCache() 可以方便你的使用

<?php
require_once 'Zend/Translate.php';

$cache = Zend_Cache::factory('Page', 'File', $frontendOptions, $backendOptions);
Zend_Translate::setCache($cache);
$translate = new Zend_Translate('gettext', '/path/to/translate.mo', 'en');

Note: 你必须 在 使用或初始化任何适配器或 Zend_Translate 的实例 之前 设置缓存，否则，直到用 addTranslation() 方法添加源文件，翻译源文件将不会缓存。

简介
Zend_Translate
Zend Framework手册 中文版
Using Translation Adapters
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Translate
  • 简介
  • Zend_Translate适配器
  • Using Translation Adapters
  • Creating source files
  • Additional features for translation
  • Plural notations for Translation


Using Translation Adapters - Zend Framework Manual

Zend_Translate适配器
Zend_Translate
Zend Framework手册 中文版
Creating source files

Using Translation Adapters

The next step is to use the adapter within your code.

Example #1 Example of single-language PHP code

  1. print "Example\n";
  2. print "=======\n";
  3. print "Here is line one\n";
  4. print "Today is the " . date("d.m.Y") . "\n";
  5. print "\n";
  6. print "Here is line two\n";

The example above shows some output with no support for translation. You probably write your code in your native language. Generally you need to translate not only the output, but also error and log messages.

The next step is to integrate Zend Translate into your existing code. Of course it is much easier if you had already written your code with translation in mind, than changing your code afterwards.

Example #2 Example of multi-lingual PHP code

  1. $translate = new Zend_Translate('gettext', '/my/path/source-de.mo', 'de');
  2. $translate->addTranslation('/path/to/translation/fr-source.mo', 'fr');
  3.
  4. print $translate->_("Example") . "\n";
  5. print "=======\n";
  6. print $translate->_("Here is line one") . "\n";
  7. printf($translate->_("Today is the %1\$s") . "\n", date('d.m.Y'));
  8. print "\n";
  9.
  10. $translate->setLocale('fr');
  11. print $translate->_("Here is line two") . "\n";

Now let's take a deeper look into what has been done and how to integrate Zend_Translate into your own code.

Create a new Zend_Translate object and define the base adapter:

  1. $translate = new Zend_Translate
  2.     'gettext',
  3.     '/path/to/translation/source-de.mo',
  4.     'de'
  5. );
In this example we chose the Gettext Adapter. We place our file source-de.mo into the directory /path/to/translation. The gettext file will have German translation included, and we also added another language source for French.

The next step is to wrap all strings which are to be translated. The simplest approach is to have only simple strings or sentences like this:

  1. print $translate->_("Example") . "\n";
  2. print "=======\n";
  3. print $translate->_("Here is line one") . "\n";
Some strings do not needed to be translated. The separating line is always a separating line, even in other languages.

Having data values integrated into a translation string is also supported through the use of embedded parameters.

  1. printf($translate->_("Today is the %1\$s") . "\n", date("d.m.Y"));
Instead of print(), use the printf() function and replace all parameters with %1\$s parts. The first is %1\$s, the second is %2\$s, and so on. This way a translation can be done without knowing the exact value. In our example, the date is always the actual day, but the string can be translated without the knowledge of the actual day.

Each string is identified in the translation storage by a message ID. You can use message IDs instead of strings in your code, like this:

  1. print $translate->_(1) . "\n";
  2. print "=======\n";
  3. print $translate->_(2) . "\n";
But doing this has several disadvantages:

You can not see what your code should output just by viewing your code.

Also you will have problems if some strings are not translated. You must always keep in mind how translation works. First Zend_Translate checks whether the specified language has a translation for the given message ID or string. If no translation string has been found it refers to the next lower level language as defined within Zend_Locale. So "de_AT" becomes "de" only. If there is no translation found for "de" either, then the original message is returned. This way you always have an output, even in case the message translation does not exist in your message storage. Zend_Translate never throws an error or exception when translating strings.

Translation Source Structures

Your next step is to create the translation sources for the languages you want to translate. Every adapter is created its own way as described here, but there are common features applicable for all adapters.

You have to decide where to store your translation source files. Using Zend_Translate you are not restricted in any way. The following structures are preferable:

  • Single structured source

    1. /application/
    2. /languages/
    3. /languages/lang.en
    4. /languages/lang.de
    5. /library/

    Positive: all source files for every languages are stored in one directory. No splitting of related files.

  • Language structured source

    1. /application/
    2. /languages/
    3. /languages/en/
    4. /languages/en/first.en
    5. /languages/en/second.en
    6. /languages/de/
    7. /languages/de/first.de
    8. /languages/de/second.de
    9. /library

    Positive: Every language is stored in their own directories. Easy translation, as every language team has to translate only one directory. Also the usage of multiple files is transparent.

  • Application structured source

    1. /application/
    2. /application/languages/
    3. /application/languages/first.en
    4. /application/languages/first.de
    5. /application/languages/second.en
    6. /application/languages/second.de
    7. /library/

    Positive: all source files for every language are stored in one directory. No splitting of related files.

    Negative: having multiple files for the same language can be problematic.

  • Gettext structured source

    1. /application/
    2. /languages/
    3. /languages/de/
    4. /languages/de/LC_MESSAGES/
    5. /languages/de/LC_MESSAGES/first.mo
    6. /languages/de/LC_MESSAGES/second.mo
    7. /languages/en/
    8. /languages/en/LC_MESSAGES/
    9. /languages/en/LC_MESSAGES/first.mo
    10. /languages/en/LC_MESSAGES/second.mo
    11. /library/

    Positive: existing gettext sources can be used without changing structure.

    Negative: having sub-sub directories may be confusing for people who have not used gettext before.

  • File structured source

    1. /application/
    2. /application/models/
    3. /application/models/MyModel.php
    4. /application/models/MyModel.de
    5. /application/models/MyModel.en
    6. /application/controllers/
    7. /application/controllers/MyController.php
    8. /application/controllers/MyController.de
    9. /application/controllers/MyController.en
    10. /library/

    Positive: translation files are localted near their source.

    Negative: too many and also small translation files result in being tendious to translate. Also every file has to be added as translation source.

Single structured and language structured source files are most usable for Zend_Translate.

So now, that we know which structure we want to have, we should create our translation source files.

Zend_Translate适配器
Zend_Translate
Zend Framework手册 中文版
Creating source files
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Translate
  • 简介
  • Zend_Translate适配器
  • Using Translation Adapters
  • Creating source files
  • Additional features for translation
  • Plural notations for Translation


Creating source files - Zend Framework Manual

Using Translation Adapters
Zend_Translate
Zend Framework手册 中文版
Additional features for translation

Creating source files

Below you will find a description of the different source formats which can be used with Zend_Translate.

Note: Note that most of the described formats should be created by using a tool or a generation process. These Tools and processes are not part of Zend Framework and for most of the described formats free tools are available.

Creating Array source files

Array source files are plain arrays. But you have to define them manually since there is no tool to aid this. But because they are so simple, it's the fastest way to look up messages if your code works as expected. It's generally the best adapter to get started with translation business.

  1. $english = array(
  2.     'message1' => 'message1',
  3.     'message2' => 'message2',
  4.     'message3' => 'message3');
  5.
  6. $german = array(
  7.     'message1' => 'Nachricht1',
  8.     'message2' => 'Nachricht2',
  9.     'message3' => 'Nachricht3');
  10.
  11. $translate = new Zend_Translate('array', $english, 'en');
  12. $translate->addTranslation($deutsch, 'de');

Since release 1.5 it is also supported to have arrays included within an external file. You just have to provide the filename and Zend_Translate will automatically include it and look for the array. See the following example for details:

  1. // myarray.php
  2. return array(
  3.     'message1' => 'Nachricht1',
  4.     'message2' => 'Nachricht2',
  5.     'message3' => 'Nachricht3');
  6.
  7. // controller
  8. $translate = new Zend_Translate('array', '/path/to/myarray.php', 'de');

Note: Files which do not return an array will fail to be included. Also any output within this file will be ignored and suppressed.

Creating Gettext source files

Gettext source files are created by GNU's gettext library. There are several free tools available that can parse your code files and create the needed gettext source files. These have the extension *.mo and they are binary files. An open source tool for creating the files is » poEdit. This tool also supports you during the translation process itself.

  1. // We accume that we have created the mo files and translated them
  2. $translate = new Zend_Translate('gettext', '/path/to/english.mo', 'en');
  3. $translate->addTranslation('/path/to/german.mo', 'de');

As you can see the adapters are used exactly the same way, with one small difference: change array to gettext. All other usages are exactly the same as with all other adapters. With the gettext adapter you no longer have to be aware of gettext's standard directory structure, bindtextdomain and textdomain. Just give the path and filename to the adapter.

Note: You should always use UTF-8 as source encoding. Otherwise you will have problems when using two different source encodings. E.g. one of your source files is encoded with ISO-8815-11 and another one with CP815. You can set only one encoding for your source file, so one of your languages probably will not display correctly.
UTF-8 is a portable format which supports all languages. When using UTF-8 for all languages, you will eliminate the problem of incompatible encodings.

Many gettext editors add adapter informations as empty translation string. This is the reason why empty strings are not translated when using the gettext adapter. Instead they are erased from the translation table and provided by the getAdapterInfo() method. It will return the adapter informations for all added gettext files as array using the filename as key.

  1. // Getting the adapter informations
  2. $translate = new Zend_Translate('gettext', '/path/to/english.mo', 'en');
  3. print_r($translate->getAdapterInfo());

Creating TMX source files

TMX source files are a new industry standard. They have the advantage of being XML files and so they are readable by every editor and of course by humans. You can either create TMX files manually with a text editor, or you can use a special tool. But most tools currently available for creating TMX source files are not freely available.

Example #1 Example TMX file

  1. <?xml version="1.0" ?>
  2. <!DOCTYPE tmx SYSTEM "tmx14.dtd">
  3. <tmx version="1.4">
  4.  <header creationtoolversion="1.0.0" datatype="winres" segtype="sentence"
  5.          adminlang="en-us" srclang="de-at" o-tmf="abc"
  6.          creationtool="XYZTool" >
  7.  </header>
  8.  <body>
  9.   <tu tuid='message1'>
  10.    <tuv xml:lang="de"><seg>Nachricht1</seg></tuv>
  11.    <tuv xml:lang="en"><seg>message1</seg></tuv>
  12.   </tu>
  13.   <tu tuid='message2'>
  14.    <tuv xml:lang="en"><seg>message2</seg></tuv>
  15.    <tuv xml:lang="de"><seg>Nachricht2</seg></tuv>
  16.   </tu>
  1. $translate = new Zend_Translate('tmx', 'path/to/mytranslation.tmx', 'en');

TMX files can have several languages within the same file. All other included languages are added automatically, so you do not have to call addLanguage().

If you want to have only specified languages from the source translated you can set the option 'defined_language' to TRUE. With this option you can add the wished languages explicitly with addLanguage(). The default value for this option is to add all languages.

Creating CSV source files

CSV source files are small and human readable. If your customers want to translate their own, you will probably use the CSV adapter.

Example #2 Example CSV file

  1. ﻿#Example csv file
  2. message1;Nachricht1
  3. message2;Nachricht2
  1. $translate = new Zend_Translate('csv', '/path/to/mytranslation.csv', 'de');
  2. $translate->addTranslation('path/to/other.csv', 'fr');

There are three different options for the CSV adapter. You can set 'delimiter', 'limit' and 'enclosure'.

The default delimiter for CSV string is ';', but with the option 'delimiter' you can decide to use another one.

The default limit for a line within a CSV file is '0'. This means that the end of a CSV line is searched automatically. If you set 'limit' to any value, then the CSV file will be read faster, but any line exceeding this limit will be truncated.

The default enclosure to use for CSV files is '"'. You can set a different one using the option 'enclosure'.

Example #3 Second CSV file example

  1. ﻿# Example CSV file
  2. "message,1",Nachricht1
  3. message2,"Nachricht,2"
  4. "message3,",Nachricht3
  1. $translate = new Zend_Translate(
  2.     'csv',
  3.     '/path/to/mytranslation.csv',
  4.     'de',
  5.     array('delimiter' => ','));
  6.
  7. $translate->addTranslation('/path/to/other.csv', 'fr');

Note: When you are using non-ASCII characters within your CSV file, like umlauts or UTF-8 chars, then you should always use enclosure. Omitting the enclosure can lead to missing characters in your translation.

Creating INI source files

INI source files are human readable but normally not very small as they also include other data beside translations. If you have data which shall be editable by your customers you can use the INI adapter.

Example #4 Example INI file

  1. [Test]
  2. ;TestPage Comment
  3. Message_1="Nachricht 1 (de)"
  4. Message_2="Nachricht 2 (de)"
  5. Message_3="Nachricht :3 (de)"
  1. $translate = new Zend_Translate('ini', '/path/to/mytranslation.ini', 'de');
  2. $translate->addTranslation('/path/to/other.ini', 'it');

INI files have several restrictions. If a value in the ini file contains any non-alphanumeric characters it needs to be enclosed in double-quotes ("). There are also reserved words which must not be used as keys for ini files. These include: NULL, yes, no, TRUE, and FALSE. Values NULL, no and FALSE results in "", yes and TRUE results in 1. Characters {}|&~![()" must not be used anywhere in the key and have a special meaning in the value. Do not use them as it will produce unexpected behaviour.

Using Translation Adapters
Zend_Translate
Zend Framework手册 中文版
Additional features for translation
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Translate
  • 简介
  • Zend_Translate适配器
  • Using Translation Adapters
  • Creating source files
  • Additional features for translation
  • Plural notations for Translation


Additional features for translation - Zend Framework Manual

Creating source files
Zend_Translate
Zend Framework手册 中文版
Plural notations for Translation

Additional features for translation

There are several additional features which are supported by Zend_Translate. Read here for these additional informations.

Options for adapters

Options can be used with all adapters. Of course the options are different for all adapters. You can set options when you create the adapter. Actually there is one option which is available to all adapters: 'clear' sets if translation data should be added to existing one or not. Standard behaviour is to add new translation data to existing one. But the translation data is only cleared for the selected language. So other languages remain untouched.

You can set options temporarily when using addTranslation($data, $locale, array $options = array()) as third and optional parameter. And you can use the method setOptions() to set the options permanently.

Example #1 Using translation options

  1. // define ':' as separator for the translation source files
  2. $options = array('delimiter' => ':');
  3. $translate = new Zend_Translate(
  4.     'csv',
  5.     '/path/to/mytranslation.csv',
  6.     'de',
  7.     $options);
  8.
  9. ...
  10.
  11. // clear the defined language and use new translation data
  12. $options = array('clear' => true);
  13. $translate->addTranslation('/path/to/new.csv', 'fr', $options);

Here you can find all available options for the different adapters with a description of their usage:

Options for translation adapters
Option | Adapter | Description | Default value
clear | all | If set to TRUE, the already read translations will be cleared. This can be used instead of creating a new instance when reading new translation data | FALSE
disableNotices | all | If set to TRUE, all notices regarding not available translations will be disabled. You should set this option to TRUE in production environment | FALSE
ignore | all | All directories and files beginning with this prefix will be ignored when searching for files. This value defaults to '.' which leads to the behavior that all hidden files will be ignored. Setting this value to 'tmp' would mean that directories and files like 'tmpImages' and 'tmpFiles' would be ignored as well as all subsequent directories | .
log | all | An instance of Zend_Log where untranslated messages and notices will be written to | NULL
logMessage | all | The message which will be written into the log | Untranslated message within '%locale%': %message%
logUntranslated | all | When this option is set to TRUE, all message IDs which can not be translated will be written into the attached log | FALSE
reload | all | When this option is set to TRUE, then files are reloaded into the cache. This option can be used to recreate the cache, or to add translations to already cached data after the cache has already been created. | FALSE
scan | all | If set to NULL, no scanning of the directory structure will be done. 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. See Automatic source detection for details | NULL
delimiter | Csv | Defines which sign is used as delimiter for separating source and translation | ;
enclosure | Csv | Defines the enclosure character to be used. Defaults to a doublequote | "
length | Csv | Defines the maximum length of a csv line. When set to 0 it will be detected automatically | 0
useId | Xliff | If you set this option to FALSE, then the source string will be used as message Id. The default for this option is TRUE, which means that the Id from the trans-unit element will be used as message Id | TRUE

When you want to have self defined options, you are also able to use them within all adapters. The setOptions() method can be used to define your option. setOptions() needs an array with the options you want to set. If an given option exists it will be signed over. You can define as much options as needed as they will not be checked by the adapter. Just make sure not to overwrite any existing option which is used by an adapter.

To return the option you can use the getOptions() method. When getOptions() is called without a parameter it will return all options set. When the optional parameter is given you will only get the specified option.

Handling languages

When working with different languages there are a few methods which will be useful.

The getLocale() method can be used to get the currently set language. It can either hold an instance of Zend_Locale or the identifier of a locale.

The setLocale() method sets a new standard language for translation. This prevents the need of setting 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. When even the downgraded language can not be found an exception will be thrown.

The isAvailable() method checks if a given language is already available. It returns TRUE if data for the given language exist.

And finally the getList() method can be used to get all currently set languages for an adapter returned as array.

Example #2 Handling languages with adapters

  1. // returns the currently set language
  2. $actual = $translate->getLocale();
  3.
  4. // you can use the optional parameter while translating
  5. echo $translate->_("my_text", "fr");
  6. // or set a new language
  7. $translate->setLocale("fr");
  8. echo $translate->_("my_text");
  9. // refer to the base language
  10. // fr_CH will be downgraded to fr
  11. $translate->setLocale("fr_CH");
  12. echo $translate->_("my_text");
  13.
  14. // check if this language exist
  15. if ($translate->isAvailable("fr")) {
  16.     // language exists
  17. }

Automatical handling of languages

Note that as long as you only add new translation sources with the addTranslation() method Zend_Translate will automatically set the best fitting language for your environment when you use one of the automatic locales which are 'auto' or 'browser'. So normally you will not need to call setLocale(). This should only be used in conjunction with automatic source detection.

The algorithm will search for the best fitting locale depending on the user's browser and your environment. See the following example for details:

Example #3 Automatically language detection

  1. // Let's expect the browser returns these language settings:
  2. // HTTP_ACCEPT_LANGUAGE = "de_AT=1;fr=1;en_US=0.8";
  3.
  4. // Example 1:
  5. // When no fitting language is found, the message ID is returned
  6. $translate = new Zend_Translate(
  7.     'gettext',
  8.     'my_it.mo',
  9.     'auto',
  10.     array('scan' => Zend_Translate::LOCALE_FILENAME));
  11.
  12. // Example 2:
  13. // Best found fitting language is 'fr'
  14. $translate = new Zend_Translate(
  15.     'gettext',
  16.     'my_fr.mo',
  17.     'auto',
  18.     array('scan' => Zend_Translate::LOCALE_FILENAME));
  19.
  20. // Example 3:
  21. // Best found fitting language is 'de' ('de_AT' will be degraded)
  22. $translate = new Zend_Translate(
  23.     'gettext',
  24.     'my_de.mo',
  25.     'auto',
  26.     array('scan' => Zend_Translate::LOCALE_FILENAME));
  27.
  28. // Example 4:
  29. // Returns 'it' as translation source and overrides the automatic settings
  30. $translate = new Zend_Translate(
  31.     'gettext',
  32.     'my_it.mo',
  33.     'auto',
  34.     array('scan' => Zend_Translate::LOCALE_FILENAME));
  35.
  36. $translate->addTranslation('my_ru.mo', 'ru');
  37. $translate->setLocale('it_IT');

After setting a language manually with the setLocale() method the automatic detection will be switched off and overridden.

If you want to use it again, you can set the language auto with setLocale() which will reactivate the automatic detection for Zend_Translate.

Since Zend Framework 1.7.0 Zend_Translate also recognises an application wide locale. You can simply set a Zend_Locale instance to the registry like shown below. With this notation you can forget about setting the locale manually with each instance when you want to use the same locale multiple times.

  1. // in your bootstrap file
  2. $locale = new Zend_Locale();
  3. Zend_Registry::set('Zend_Locale', $locale);
  4.
  5. // default language when requested language is not available
  6. $defaultlanguage = 'en';
  7.
  8. // somewhere in your application
  9. $translate = new Zend_Translate('gettext', 'my_de.mo');
  10.
  11. if (!$translate->isAvailable($locale->getLanguage())) {
  12.     // not available languages are rerouted to another language
  13.     $translate->setLocale($defaultlanguage);
  14. }
  15.
  16. $translate->getLocale();

Automatic source detection

Zend_Translate can detect translation sources automatically. So you don't have to declare each source file manually. You can let Zend_Translate do this job and scan the complete directory structure for source files.

Note: Automatic source detection is available since Zend Framework version 1.5 .

The usage is quite the same as initiating a single translation source with one difference. You must give a directory which has to be scanned instead a file.

Example #4 Scanning a directory structure for sources

  1. // assuming we have the following structure
  2. //  /language/
  3. //  /language/login/login.tmx
  4. //  /language/logout/logout.tmx
  5. //  /language/error/loginerror.tmx
  6. //  /language/error/logouterror.tmx
  7.
  8. $translate = new Zend_Translate('tmx', '/language');

So Zend_Translate does not only search the given directory, but also all subdirectories for translation source files. This makes the usage quite simple. But Zend_Translate will ignore all files which are not sources or which produce failures while reading the translation data. So you have to make sure that all of your translation sources are correct and readable because you will not get any failure if a file is bogus or can not be read.

Note: Depending on how deep your directory structure is and how much files are within this structure it can take a long time for Zend_Translate to complete.

In our example we have used the TMX format which includes the language to be used within the source. But many of the other source formats are not able to include the language within the file. Even this sources can be used with automatic scanning if you do some pre-requisits as described below:

Language through naming directories

One way to include automatic language detection is to name the directories related to the language which is used for the sources within this directory. This is the easiest way and is used for example within standard gettext implementations.

Zend_Translate needs the 'scan' option to know that it should search the names of all directories for languages. See the following example for details:

Example #5 Directory scanning for languages

  1. // assuming we have the following structure
  2. //  /language/
  3. //  /language/de/login/login.mo
  4. //  /language/de/error/loginerror.mo
  5. //  /language/en/login/login.mo
  6. //  /language/en/error/loginerror.mo
  7.
  8. $translate = new Zend_Translate(
  9.     'gettext',
  10.     '/language',
  11.     null,
  12.     array('scan' => Zend_Translate::LOCALE_DIRECTORY));

Note: This works only for adapters which do not include the language within the source file. Using this option for example with TMX will be ignored. Also language definitions within the filename will be ignored when using this option.

Note: You should be aware if you have several subdirectories under the same structure. Assuming we have a structure like /language/module/de/en/file.mo. In this case the path contains multiple strings which would be detected as locale. It could be either de or en. In such a case the behaviour is undefined and it is recommended to use file detection in such situations.

Language through filenames

Another way to detect the language automatically is to use special filenames. You can either name the complete file or parts of a file after the used language. To use this way of detection you will have to set the 'scan' option at initiation. There are several ways of naming the sourcefiles which are described below:

Example #6 Filename scanning for languages

  1. // assuming we have the following structure
  2. //  /language/
  3. //  /language/login/login_en.mo
  4. //  /language/login/login_de.mo
  5. //  /language/error/loginerror_en.mo
  6. //  /language/error/loginerror_de.mo
  7.
  8. $translate = new Zend_Translate(
  9.     'gettext',
  10.     '/language',
  11.     null,
  12.     array('scan' => Zend_Translate::LOCALE_FILENAME));

Complete filename

Having the whole file named after the language is the simplest way but only viable if you have only one file per language.

/languages/
/languages/en.mo
/languages/de.mo
/languages/es.mo

Extension of the file

Another simple way to use the extension of the file for language detection. But this may be confusing since you will no longer have an idea which extension the file originally had.

/languages/
/languages/view.en
/languages/view.de
/languages/view.es

Filename tokens

Zend_Translate is also capable of detecting the language if it is included within the filename. But if you go this way you will have to separate the language with a token. There are three supported tokens which can be used: a dot '.', an underscore '_', or a hyphen '-'.

/languages/
/languages/view_en.mo -> detects english
/languages/view_de.mo -> detects german
/languages/view_it.mo -> detects italian

The first found string delimited by a token which can be interpreted as a locale will be used. See the following example for details.

/languages/
/languages/view_en_de.mo -> detects english
/languages/view_en_es.mo -> detects english and overwrites the first file
/languages/view_it_it.mo -> detects italian

All three tokens are used to detect the locale. When the filename contains multiple tokens, the first found token depends on the order of the tokens which are used. See the following example for details.

/languages/
/languages/view_en-it.mo -> detects english because '_' will be used before '-'
/languages/view-en_it.mo -> detects italian because '_' will be used before '-'
/languages/view_en.it.mo -> detects italian because '.' will be used before '_'

Checking for translations

Normally text will be translated without any computation. But sometimes it is necessary to know if a text is translated or not, therefor the isTranslated() method can be used.

isTranslated($messageId, $original = false, $locale = null) takes the text you want to check as its first parameter, and as optional third parameter the locale for which you want to do the check. The optional second parameter declares whether translation is fixed to the declared language or a lower set of translations can be used. If you have a text which can be returned for 'en' but not for 'en_US' you will normally get the translation returned, but by setting $original to TRUE, isTranslated() will return FALSE.

Example #7 Checking if a text is translatable

  1. $english = array(
  2.     'message1' => 'Nachricht 1',
  3.     'message2' => 'Nachricht 2',
  4.     'message3' => 'Nachricht 3');
  5.
  6. $translate = new Zend_Translate('array', $english, 'de_AT');
  7.
  8. if ($translate->isTranslated('message1')) {
  9.     print "'message1' can be translated";
  10. }
  11.
  12. if (!($translate->isTranslated('message1', true, 'de'))) {
  13.     print "'message1' can not be translated to 'de'"
  14.         . " as it's available only in 'de_AT'";
  15. }
  16.
  17. if ($translate->isTranslated('message1', false, 'de')) {
  18.     print "'message1' can be translated in 'de_AT' as it falls back to 'de'";
  19. }

How to log not found translations

When you have a bigger site or you are creating the translation files manually, you often have the problem that some messages are not translated. But there is an easy solution for you when you are using Zend_Translate.

You have to follow two or three simple steps. First, you have to create an instance of Zend_Log. Then you have to attach this instance to Zend_Translate. See the following example:

Example #8 Log translations

  1. $translate = new Zend_Translate('gettext', $path, 'de');
  2.
  3. // Create a log instance
  4. $writer = new Zend_Log_Writer_Stream('/path/to/file.log');
  5. $log    = new Zend_Log($writer);
  6.
  7. // Attach it to the translation instance
  8. $translate->setOptions(array(
  9.     'log'             => $log,
  10.     'logUntranslated' => true));
  11.
  12. $translate->translate('unknown string');

Now you will have a new notice in the log: Untranslated message within 'de': unknown string.

Note: You should note that any translation which can not be found will be logged. This means all translations when a user requests a language which is not supported. Also every request for a message which can not be translated will be logged. Be aware, that 100 people requesting the same translation, will result 100 logged notices.

This feature can not only be used to log messages but also to attach this untranslated messages into an empty translation file. To do so you will have to write your own log writer which writes the format you want to have and strips the prepending "Untranslated message".

You can also set the 'logMessage' option when you want to have your own log message. Use the '%message%' token for placing the messageId within your log message, and the '%locale%' token for the requested locale. See the following example for a self defined log message:

Example #9 Self defined log messages

  1. $translate = new Zend_Translate('gettext', $path, 'de');
  2.
  3. // Create a log instance
  4. $writer = new Zend_Log_Writer_Stream('/path/to/file.log');
  5. $log    = new Zend_Log($writer);
  6.
  7. // Attach it to the translation instance
  8. $translate->setOptions(array(
  9.     'log'             => $log,
  10.     'logMessage'      => "Missing '%message%' within locale '%locale%'",
  11.     'logUntranslated' => true));
  12.
  13. $translate->translate('unknown string');

Accessing source data

Sometimes it is useful to have access to the translation source data. Therefor the following two functions are provided.

The getMessageIds($locale = null) method returns all known message IDs as array.

The getMessages($locale = null) method returns the complete translation source as an array. The message ID is used as key and the translation data as value.

Both methods accept an optional parameter $locale which, if set, returns the translation data for the specified language. If this parameter is not given, the actual set language will be used. Keep in mind that normally all translations should be available in all languages. Which means that in a normal situation you will not have to set this parameter.

Additionally the getMessages() method can be used to return the complete translation dictionary using the pseudo-locale 'all'. This will return all available translation data for each added locale.

Note: Attention: the returned array can be very big, depending on the number of added locales and the amount of translation data.

Example #10 Handling languages with adapters

  1. // returns all known message IDs
  2. $messageIds = $translate->getMessageIds();
  3. print_r($messageIds);
  4.
  5. // or just for the specified language
  6. $messageIds = $translate->getMessageIds('en_US');
  7. print_r($messageIds);
  8.
  9. // returns all the complete translation data
  10. $source = $translate->getMessages();
  11. print_r($source);
Creating source files
Zend_Translate
Zend Framework手册 中文版
Plural notations for Translation
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Translate
  • 简介
  • Zend_Translate适配器
  • Using Translation Adapters
  • Creating source files
  • Additional features for translation
  • Plural notations for Translation


Plural notations for Translation - Zend Framework Manual

Additional features for translation
Zend_Translate
Zend Framework手册 中文版
Zend_Uri

Plural notations for Translation

As of Zend Framework 1.9, Zend_Translate is able to provide plural support. Professional translation will always have the need to use plurals as they are native in almost all languages.

So what are plurals? Generally spoken plurals are words which take into account numeric meanings. But as you may imagine each language has it's own definition of plurals. English, for example, supports one plural. We have a singular definition, for example "car", which means implicit one car, and we have the plural definition, "cars" which could mean more than one car but also zero cars. Other languages like russian or polish have more plurals and also the rules for plurals are different.

When you want to use plurals with Zend_Translate you must not need to know how the plurals are defined, only the translator must know as he does the translation. The only information you need to have is the language.

There are two ways for using plurals... the traditional one, which means that you use a own method, and a modern one, which allows you to do plural translations with the same method as normal translations.

Traditional plural translations

People who worked with gettext in past will be more common with traditional plural translations. There is a own plural() method which can be used for plural translations.

Example #1 Example of traditional plural translations

The plural() method accepts 4 parameters. The first parameter is the singular messageId, the second is the plural messageId and the third is the number or amount.

The number will be used to detect the plural which has to be returned. A optional forth parameter can be used to give a locale which will be used to return the translation.

  1. $translate = new Zend_Translate('gettext', '/path/to/german.mo', 'de');
  2. $translate->plural('Car', 'Cars', $number);

Modern plural translations

As traditional plural translations are restricted to source code using english plurals we added a new way for plural translations. It allows to use the same translate() for standard and for plural translations.

To use plural translations with translate() you need to give an array as messageId instead of an string. This array must have the original plural messageId's, then the amount and at last an optional locale when your given messageId's are not in english notation.

Example #2 Example of modern plural translations

When we want to translate the same plural definitions like in the previous our example would have to be defined like below.

  1. $translate = new Zend_Translate('gettext', '/path/to/german.mo', 'de');
  2. $translate->translate(array('Car', 'Cars', $number));

Using modern plural translations it is also possible to use any language as source for messageId's.

Example #3 Example of modern plural translations using a different source language

Let's expect we want to use russian and let's also expect that the given messageId's are russian and not english.

  1. $translate = new Zend_Translate('gettext', '/path/to/german.mo', 'de');
  2. $translate->translate(array('Car',
  3.                             'Cars first plural',
  4.                             'Cars second plural',
  5.                             $number,
  6.                             'ru'));

As you can see you can give more than just the one english plural. But you must give the source language in this case so Zend_Translate knows which plural rules it has to apply.

When you omit the plural language then english will be used per default and any additional plural definition will be ignored.

Plural source files

Not all source formats support plural forms. Look into this list for details:

Plural support
Adapter | Plurals supported
Array | yes
Csv | yes
Gettext | yes
Ini | no
Qt | no
Tbx | no
Tmx | no
Xliff | no
XmlTm | no

Below you can find examples of plural defined source files.

Array source with plural definitions

An array with plural definitions has to look like the following example.

  1. array(
  2.     'plural_0' => array(
  3.         'plural_0 (ru)',
  4.         'plural_1 (ru)',
  5.         'plural_2 (ru)',
  6.         'plural_3 (ru)'
  7.     ),
  8.     'plural_1' => ''
  9. );

In the above example plural_0 and plural_1 are the plural definitions from the source code. And the array at plural_0 has all translated plural forms available. Take a look at the following example with real content and translation from english source to german.

  1. array(
  2.     'Car' => array(
  3.         'Auto',
  4.         'Autos'
  5.     ),
  6.     'Cars' => ''
  7. );

When your translated language supports more plural forms then simply add them to the array below the first plural form. When your source language suppors more plural forms, than simply add a new empty translation.

Csv source with plural definitions

A csv file with plural definitions has to look like the following example.

  1. "plural_0";"plural_0 (ru)";"plural_1 (ru)";"plural_2 (ru)";"plural_3 (ru)"
  2. "plural_1";

All translated plural forms have to be added after the first plural of the source language. And all further plural forms of the source language have to be added below but without translation. Note that you must add a delimiter to empty source plurals.

Gettext source with plural definitions

Gettext sources support plural forms out of the box. There is no need for adoption as the *.mo file will contain all necessary data.

Note: Note that gettext does not support the usage of source languages which are not using english plural forms. When you plan to use a source language which supports other plural forms like russian for example, then you can not use gettext sources.

Custom plural rules

In rare cases it could be useful to be able to define own plural rules. See chinese for example. This language defines two plural rules. Per default it does not use plurals. But in rare cases it uses a rule like (number == 1) ? 0 : 1.

Also when you want to use a language which has no known plural rules, and would want to define your own rules.

This can be done by using Zend_Translate_Plural::setRule(). The method expects two parameters which must be given. A rule, which is simply a callback to a self defined method. And a locale for which the rule will be used.

Your rule could look like this:

  1. public function MyRule($number) {
  2.     return ($number == 10) ? 0 : 1;
  3. }

As you see, your rule must accept one parameter. It is the number which you will use to return which plural the translation has to use. In our example we defined that when we get a '10' the plural definition 0 has to be used, in all other cases we're using 1.

Your rules can be as simple or as complicated as you want. You must only return an integer value. The plural definition 0 stands for singular translation, and 1 stands for the first plural rule.

To activate your rule, and to link it to the wished locale, you have to call it like this:

  1. Zend_Translate_Plural::setPlural('MyPlural', 'zh');

Now we linked our plural definition to the chinese language.

You can define one plural rule for every language. But you should be aware that you set the plural rules before you are doing translations.

Note: Define custom plurals only when needed
 Zend_Translate defines plurals for most known languages. You should not define own plurals when you are not in need. The default rules work most of time.

Additional features for translation
Zend_Translate
Zend Framework手册 中文版
Zend_Uri
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Translate
  • 简介
  • Zend_Translate适配器
  • Using Translation Adapters
  • Creating source files
  • Additional features for translation
  • Plural notations for Translation


Zend_Uri - Zend Framework Manual

Plural notations for Translation
Zend Framework Reference
Zend Framework手册 中文版
Zend_Uri

Zend_Uri

Table of Contents
  • Zend_Uri
Plural notations for Translation
Zend Framework Reference
Zend Framework手册 中文版
Zend_Uri
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


Zend_Uri - Zend Framework Manual

Zend_Uri
Zend_Uri
Zend Framework手册 中文版
Zend_Validate

Zend_Uri

概述

Zend_Uri 是一个辅助于操作和验证» 统一资源标识符 (URIs)的组件. Zend_Uri 的存在主要是为其他组件服务的,比如Zend_Http_Client,但是作为一个独立的工具也是有用的.

URIs 总是以一个schema(模式,协议)开始,后跟一个冒号(colon).Zend_Uri类提供一个工厂, 返回一个它本身的 适应于每种模式(scheme)的 子类,子类被命名为Zend_Uri_<scheme>, <scheme>是首字母大写的模式名称.一个例外是HTTPS,它也是由Zend_Uri_Http处理的.

新建一个URI

如果仅有一个模式被传递给Zend_Uri::factory(),Zend_Uri将从头构造一个新的URI.

Example #1 使用Zend_Uri::factory()创建一个新的URI

<?php

require_once 'Zend/Uri.php';

// 重新创建一个新的URI,仅传递模式.
$uri = Zend_Uri::factory('http');

// $uri instanceof Zend_Uri_Http

?>

从头创建一个的新的URI,仅仅需要传递模式给Zend_Uri::factory() [1] . 如果传递了一个未支持的模式,Zend_Uri_Exception异常将被抛出.

如果传递的模式或者URI被支持,Zend_Uri::factory()返回一个它本身的 适应于特定模式(scheme)的 子类

操作现有的URI

要操作一个现有的URL,把整个URI传递给Zend_Uri::factory().

Example #2 使用Zend_Uri::factory()操作一个现有的URI

<?php

require_once 'Zend/Uri.php';

// 操作一个现有的URI,把他传入到Zend_Uri::factory().
$uri = Zend_Uri::factory('http://www.zend.com');

// $uri instanceof Zend_Uri_Http

?>

这个URI将被解析并且验证.如果发现它是无效的,Zend_Uri_Exception异常立即抛出.否则Zend_Uri::factory() 返回一个它本身的 适应于特定模式(scheme)的 子类

URI 验证

Zend_Uri::check() 函数仅在需要验证一个现有的URI时使用.

Example #3 使用Zend_Uri::check()进行URI 验证

<?php

require_once 'Zend/Uri.php';

// 验证一个给定的URI是否是格式良好的
$valid = Zend_Uri::check('http://uri.in.question');

// 对于一个有效的URI,$valid为TRUE,否则为FALSE

?>

Zend_Uri::check() 返回布尔值,它比使用Zend_Uri::factory()更便捷,并且能够捕获异常.

公共实例方法

每个Zend_Uri子类的实例(如:Zend_Uri_Http)有多个 有用的 处理任何类型的 URI的实例方法.

取得URI的Schema

URI模式是冒号之前的部分.例如http://www.zend.com的模式是http.

Example #4 从Zend_Uri_* 对象取得模式

<?php

require_once 'Zend/Uri.php';

$uri = Zend_Uri::factory('http://www.zend.com');

$scheme = $uri->getScheme();  // "http"

?>

getScheme()实例方法仅返回URI对象的模式部分.

取得整个URI

Example #5 从一个Zend_Uri_* 对象取得整个URI

<?php

require_once 'Zend/Uri.php';

$uri = Zend_Uri::factory('http://www.zend.com');

echo $uri->getUri();  // "http://www.zend.com"

?>

getUri()方法返回整个URI的字符串标识.

验证URI

Zend_Uri::factory()总是验证传递给它的任何URI,如果给定的URI被认为是无效的,它将不会实例化一个新的Zend_Uri 子类.但是 Zend_Uri子类为 一个新URI 或者 一个现有的有效的URL 被实例化后,在操作后 该URI可能会变得无效.

Example #6 验证一个 Zend_Uri_* 对象

<?php

require_once 'Zend/Uri.php';

$uri = Zend_Uri::factory('http://www.zend.com');

$isValid = $uri->valid();  // TRUE

?>

valid()实例方法检查URI对象是否仍是有效的.

[1] 在撰写本文时,Zend_Uri仅支持HTTP和HTTPS模式.
Zend_Uri
Zend_Uri
Zend Framework手册 中文版
Zend_Validate
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Uri
  • Zend_Uri


Zend_Validate - Zend Framework Manual

Zend_Uri
Zend Framework Reference
Zend Framework手册 中文版
简介

Zend_Validate

Table of Contents
  • 简介
  • 标准校验类
  • 校验器链
  • 编写校验器
  • Validation Messages
Zend_Uri
Zend Framework Reference
Zend Framework手册 中文版
简介
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


简介 - Zend Framework Manual

Zend_Validate
Zend_Validate
Zend Framework手册 中文版
标准校验类

简介

Zend_Validate 组件提供一组通用的校验器。它也提供了一个简单的校验器链机制，即在用户定义的顺序下，多个校验器可以被用于单个的数据。

什么是校验器（validator）?

校验器根据要求检查它的输入并产生一个布尔结果--是否输入被成功校验。如果输入不符合要求，校验器另外地提供信息来说明输入不符合要求。

例如，一个 web 应用可能要求一个用户名的长度在6 到12个字符并可能只包含数字和文字。一个校验器可以被用来确保用户名符合要求。如果一个用户名不符合一个或者全部两个要求，知道它到底不符合哪个要求将非常有用。

校验器的基本用法

用这种方法定义校验为Zend_Validate_Interface提供了基础，它定义了两个方法，isValid() 和 getMessages()。isValid()方法根据提供的值来校验，当且仅当这个值通过校验条件，它返回true。

如果isValid()返回false，getMessages() 返回一个消息数组来解释校验失败的原因。数组键是识别校验失败原因的短字符串，数组的值是相对应的人类可读的字符串消息。键和值是独立于类的；每个校验类定义它自己的校验失败消息和独一无二的键来识别它们。每个类也有const定义用来为校验失败原因匹配每个识别器。

Note: getMessages() 方法只为最近isValid()的调用返回校验失败消息。对isValid()每个调用清除由前一个isValid()调用导致的任何消息和错误，因为很可能每个isValid()调用用于不同的输入值。

下面的例子示例一个e-mail地址的校验：

<?php
require_once 'Zend/Validate/EmailAddress.php';

$validator = new Zend_Validate_EmailAddress();

if ($validator->isValid($email)) {
    // email 有效
} else {
    // email 无效; 打印原因
    foreach ($validator->getMessages() as $messageID => $message) {
        echo "Validation failure '$messageID': $message\n";
    }
}

定制消息

校验类提供了一个setMessage()方法，你可以指定校验失败后由getMessages()返回的消息的格式。这个方法的第一个参数是一个包含错误信息的的字符串。你可以在字符串中包含令牌，它将被和校验器相关的数据替换。所有的校验器都支持令牌 %value%；这被你传递给isValid()的值替换。其它的令牌按情况在每个校验类中被支持。例如，%max%是一个被Zend_Validate_LessThan支持的令牌。The getMessageVariables()方法返回一个被校验器支持的令牌变量的数组。

第二个可选的参数是一个字符串，它识别是否校验失败消息模板被设置，当校验类定义了多于一个失败的原因的时候，这很有用。如果你忽略第二个参数，setMessage()假定你指定的消息应该被用为在校验类中声明的第一个消息模板。许多校验类只定义了一个错误消息模板，所以不需要指定哪个消息模板需要修改。

<?php
require_once 'Zend/Validate/StringLength.php';

$validator = new Zend_Validate_StringLength(8);

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

    // echoes "The string 'word' is too short; it must be at least 8 characters"
}

你可以用setMessages()方法设置多个消息。它的参数是一个包含key/message对的数组。

<?php
require_once 'Zend/Validate/StringLength.php';

$validator = new Zend_Validate_StringLength(8, 12);

$validator->setMessages( array(
    Zend_Validate_StringLength::TOO_SHORT => 'The string \'%value%\' is too short',
    Zend_Validate_StringLength::TOO_LONG  => 'The string \'%value%\' is too long'
));

如果你的应用程序要求更灵活的校验失败报告，你可以访问和消息令牌同名的属性，这个消息令牌由给定的校验类支持。value属性在校验器中总是有效；它是一个你指定作为isValid()的参数的值。其他属性按照情况在每个校验类中被支持。

<?php
require_once 'Zend/Validate/StringLength.php';

$validator = new Zend_Validate_StringLength(8, 12);

if (!validator->isValid('word')) {
    echo 'Word failed: '
        . $validator->value
        . '; its length is not between '
        . $validator->min
        . ' and '
        . $validator->max
        . "\n";
}

使用静态 is() 方法

如果加载一个校验类并创建这个校验器的实例不方便，你可以使用静态方法Zend_Validate::is()作为可选的调用风格。第一个参数是一个数据输入值，你将把它传递给isValid()方法。第二个参数是一个字符串，它和校验类的基本名字对应，和Zend_Validate名字空间相关。is()方法自动加载这个类，创建一个实例，并应用isValid()方法到数据输入。

<?php
require_once 'Zend/Validate.php';

if (Zend_Validate::is($email, 'EmailAddress')) {
    // 是, email 有效
}

如果校验器需要，你也可以传递一个构造器参数的数组。

<?php
require_once 'Zend/Validate.php';

if (Zend_Validate::is($value, 'Between', array(1, 12))) {
    // Yes, $value is between 1 and 12
}

和isValid()方法一样，is()方法返回一个布尔值。当使用静态is()方法时，校验失败消息不可用。

静态用法对于调用专用校验器可能方便，但如果为多重输入运行一个校验器，使用非静态用法更有效，创建一个校验器对象的实例并调用isValid()方法。

并且，Zend_Filter_Input 类允许你按需求实例化和运行多个过滤器和校验器类来处理输入数据集合，参见Zend_Filter_Input。

Zend_Validate
Zend_Validate
Zend Framework手册 中文版
标准校验类
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Validate
  • 简介
  • 标准校验类
  • 校验器链
  • 编写校验器
  • Validation Messages


标准校验类 - Zend Framework Manual

简介
Zend_Validate
Zend Framework手册 中文版
校验器链

标准校验类

Zend Framework 带有一组标准的校验类供你使用。

Alnum

当且仅当$value只包含字母和数字字符，返回 true。这个校验器包括一个考虑空白字符是否有效的选项。

Alpha

当且仅当$value只包含字母字符，返回 true。这个校验器包括一个考虑空白字符是否有效的选项。

Barcode

这个校验器是个带有条码类型的实例，条码类型是根据你希望用来校验条码值而定。它目前支持 "UPC-A" （通用产品码）和 "EAN-13" （欧洲商品码）条码类型，当且仅当输入成功通过条码校验算法的校验，isValid() 返回 true。你应该从输入中删除除了数字0到9（0-9）以外的其它字符，然后传递给校验器。

Between

当且仅当$value在最小值和最大值之间，返回true。缺省地，比较包含边界值（$value可以等于边界值），尽管为了做精确地比较这个可以被覆盖。所谓精确地比较，就是$value必须大于最小值和小于最大值。

Ccnum

当且仅当$value遵循Luhn(mod-10 checksum)算法，返回true 。

日期

当$value是一个格式为YYYY-MM-DD的有效日期，返回true 。如果locale 选项被设置那么日期将根据locale来校验，如果format 选项被设置成这个格式用来校验。关于选项参数的细节参见Zend_Date::isDate()。

数字

当且仅当$value只包含数字字符，返回 true。

Email 地址

Zend_Validate_EmailAddress允许你校验一个email地址。首先校验器把email地址分成local-part和@hostname并试图按照email地址和主机名的规范来匹配它。

基本用法

一个基本用法的例子如下：

$validator = new Zend_Validate_EmailAddress();
if ($validator->isValid($email)) {
    // email appears to be valid
} else {
    // email is invalid; print the reasons
    foreach ($validator->getMessages() as $message) {
        echo "$message\n";
    }
}
这个例子匹配email地址$email并在匹配失败的时候用$validator->getMessages()来获得有用的错误信息。

复杂的local parts

Zend_Validate_EmailAddress根据RFC2822来匹配任何有效的email地址。例如，有效的email地址包括bob@domain.com, bob+jones@domain.us, "bob@jones"@domain.com 和 "bob jones"@domain.com。一些过时的email格式目前不再校验（例如email地址中的回车符或"\"符）。

校验不同类型的主机名

Email地址中的主机名部分依靠Zend_Validate_Hostname来校验。尽管你希望IP地址和本地主机名也被接受，但缺省地只有像domain.com格式的DNS主机名被接受。 当然如果你想如愿，需要实例化Zend_Validate_EmailAddress并传递一个参数来指明哪种主机名你想接受。更多的细节包含在Zend_Validate_Hostname中。 下面的例子显示如何同时接受DNS和本地主机名：

$validator = new Zend_Validate_EmailAddress(Zend_Validate_Hostname::ALLOW_DNS | Zend_Validate_Hostname::ALLOW_LOCAL);
if ($validator->isValid($email)) {
    // email appears to be valid
} else {
    // email is invalid; print the reasons
    foreach ($validator->getMessages() as $message) {
        echo "$message\n";
    }
}

检查主机名是否确实接受email

email地址的格式正确并不意味着这个email地址确实存在。为解决这个问题，你可以用MX校验来检查一个MX(email)条目的主机名是否存在于DNS的纪录里。这将告诉你这个主机名接受email，但并不告诉你确切的email地址是有效的。

MX 检查不是缺省地激活的，并且目前只支持UNIX平台。为激活MX检查，你可以传递第二个参数给Zend_Validate_EmailAddress构造器。

$validator = new Zend_Validate_EmailAddress(Zend_Validate_Hostname::ALLOW_DNS, true);
另外你可以传递 true 或 false 给$validator->setValidateMx() 来激活或禁止 MX 校验。

用激活这个设置的网络函数将用来为你所想校验的email地址的主机名中的MX记录的存在做检查。请注意这将可能把你的脚本变慢。

校验国际域名

Zend_Validate_EmailAddress 也将匹配存在于某些域名中的国际字符。这就是国际域名（IDN）支持。这个是缺省激活，你可以通过用存在于 Zend_Validate_EmailAddress 中的内部的 Zend_Validate_Hostname 对象来改变设置来禁止。

$validator->hostnameValidator->setValidateIdn(false);
关于 setValidateIdn() 更多的信息在Zend_Validate_Hostname 文档中。

请注意你有你允许DNS 主机名被校验，国际域名（IDNs）才被校验。

校验顶级域名

缺省地用已知的TLDs列表来检查主机名。你可以通过用存在于Zend_Validate_EmailAddress 中的内部的 Zend_Validate_Hostname 对象来改变设置来禁止。

$validator->hostnameValidator->setValidateTld(false);
关于 setValidateTld() 更多的信息在Zend_Validate_Hostname 文档中。

请注意你有你允许DNS 主机名被校验，顶级域名（TLDs）才被校验。

浮点数

当且仅当$value是一个浮点数值，返回 true。

GreaterThan

当且仅当$value大于最小值，返回 true。

十六进制数

当且仅当$value只包含十六进制的数字字符，返回 true。

主机名

Zend_Validate_Hostname允许你根据一组已知的规范来校验主机名。它检查三种不同的主机名：DNS主机名（例如domain.com），IP地址（例如1.2.3.4），和本地主机名（例如localhost）。缺省地，只有DNS主机名被匹配。

基本用法

一个基本用法的例子如下：

<?php
require_once 'Zend/Validate/Hostname.php';
$validator = new Zend_Validate_Hostname();
if ($validator->isValid($hostname)) {
    // hostname appears to be valid
} else {
    // hostname is invalid; print the reasons
    foreach ($validator->getMessages() as $message) {
        echo "$message\n";
    }
}
这个例子匹配主机名$hostname并在匹配失败的时候用$validator->getMessages()来获得有用的错误信息。

校验不同类型的主机名

你可能发现你也想匹配IP地址，本地主机名，或者是所有允许类型的组合。这个可以在当你实例化它的时候通过传递参数给Zend_Validate_Hostname来实现。 参数应该是一个整型数，它来决定哪种主机名被允许。我们鼓励你使用常量。

Zend_Validate_Hostname 常量是： ALLOW_DNS 允许DNS主机名， ALLOW_IP 允许IP地址， ALLOW_LOCAL 允许本地网络名，和ALLOW_ALL 允许所有三种类型。 你可以用下面的例子仅仅检查IP地址：

<?php
require_once 'Zend/Validate/Hostname.php';
$validator = new Zend_Validate_Hostname(Zend_Validate_Hostname::ALLOW_IP);
if ($validator->isValid($hostname)) {
    // hostname appears to be valid
} else {
    // hostname is invalid; print the reasons
    foreach ($validator->getMessages() as $message) {
        echo "$message\n";
    }
}

你可以用这些类型的组合，也可以用ALLOW_ALL来接受所有主机名类型。例如，你可以通过如下例子实例化Zend_Validate_Hostname对象来接受DNS和本地主机名:

<?php

$validator = new Zend_Validate_Hostname(Zend_Validate_Hostname::ALLOW_DNS | Zend_Validate_Hostname::ALLOW_LOCAL);}

校验国际域名

一些国家代码顶级域名（ccTLDs），例如'de'（德国），在域名中支持国际字符。这些就是大家所知的国际域名（IDN）。这些域名可以用Zend_Validate_Hostname通过用于校验处理的扩展字符来匹配。

目前支持ccTLDs的有：

  • at (Austria)

  • ch (Switzerland)

  • li (Liechtenstein)

  • de (Germany)

  • fi (Finland)

  • hu (Hungary)

  • no (Norway)

  • se (Sweden)

匹配IDN域名就像使用标准主机名校验器一样简单，因为IDN匹配是缺省激活的。如果你想禁止IDN校验，可以通过传递参数给Zend_validate_Hostname构造器或通过$validator->setValidateIdn()方法来实现。

你可以象下面通过传递第二个参数给Zend_Validate_Hostname构造器来禁止IDN校验。

<?php

$validator = new Zend_Validate_Hostname(Zend_Validate_Hostname::ALLOW_DNS, false);
另外你可以通过传递 TRUE 或 FALSE 给 $validator->setValidateIdn() 来激活或者禁止 IDN 校验。如果你试图匹配一个当前不被支持的IDN主机名，并且如果有国际字符在其中，校验很可能会失败。当指定附加字符的ccTLD文件在Zend/Validate/Hostname下不存在时，一个正常的主机名校验将被执行。（这就是在解释上句话中为什么校验会失败，Jason 注）

请注意只有当你允许DNS主机名被校验，IDNs才能被校验。

校验顶级域名

缺省地主机名通过已知的TLDs列表来检查。如果不需要这个功能，它可以被禁止，就像禁止IDN支持一样。你可以通过传递第三个参数给Zend_Validate_Hostname构造器来禁止TLD校验。在下面的例子中，我们通过第二个参数来支持IDN校验。

<?php

$validator = new Zend_Validate_Hostname(Zend_Validate_Hostname::ALLOW_DNS, true, false);
另外，你可以通过传递 TRUE 或 FALSE 给 $validator->setValidateTld() 来激活或禁止 TLD 校验。

请注意只有当你允许DNS主机名被校验，TLDs才能被校验。

InArray

当且仅当一个"needle"$value包含在一个"haystack"数组，返回 true。如果精确选项是true，那么$value的类型也被检查。

整数

当且仅当$value是一个有效的整数，返回 true。

Ip

当且仅当$value是一个有效的IP地址，返回 true。

LessThan

当且仅当$value小于最大值，返回 true。

NotEmpty

当且仅当$value非空，返回 true。

Regex

当且仅当$value匹配一个正则表达式，返回 true。

StringLength

当且仅当字串长度值$value至少是最小值并不大于最大值（当max选项不是null），返回 true。从1.5.0版开始，如果最小长度被设置为一个大于已设定的最大长度的值，setMin()方法抛出一个异常，并且如果最大长度值被设置为小于一个已设定的最小长度的值，setMax()方法抛出一个异常。从1.0.2版开始，基于» iconv.internal_encoding 的当前值，这个类支持UTF-8和其它字符编码。

简介
Zend_Validate
Zend Framework手册 中文版
校验器链
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Validate
  • 简介
  • 标准校验类
  • 校验器链
  • 编写校验器
  • Validation Messages


校验器链 - Zend Framework Manual

标准校验类
Zend_Validate
Zend Framework手册 中文版
编写校验器

校验器链

通常，多个校验器按照特定的顺序被用于某些值。下面的代码示范一个办法去解决introduction中的例子的要求，即用户名必须在6到12个字符的文字数字组合：

// Create a validator chain and add validators to it
$validatorChain = new Zend_Validate();
$validatorChain->addValidator(new Zend_Validate_StringLength(6, 12))
               ->addValidator(new Zend_Validate_Alnum());

// Validate the username
if ($validatorChain->isValid($username)) {
    // username passed validation
} else {
    // username failed validation; print reasons
    foreach ($validatorChain->getMessages() as $message) {
        echo "$message\n";
    }
校验器按照它们被加到Zend_Validate的顺序执行。在上面的例子中，用户名首先被检查来确保它的长度在6到12个字符，然后它被检查来确保它只包含文字和数字。不管第一个校验（检查长度是否6到12）是否成功，第二个校验（检查是否文字数字组合）总被执行。这就意味着如果两个校验都失败，getMessages()将为两个校验器都返回失败信息。

在某些情况下，如果校验过程失败， 让校验器中断校验器链符合常识。Zend_Validate 在addValidator()方法中使用第二个参数来支持这样的用例。通过设置$breakChainOnFailure为true，如果校验失败，校验器将中断校验器链执行，这样就避免了在这个情形下运行其他已经被决定是不必要的或不适当的校验。如果上面的例子被写成如下，如果字串长度校验失败，文字数字组合校验就不会发生：

$validatorChain->addValidator(new Zend_Validate_StringLength(6, 12), true)
               ->addValidator(new Zend_Validate_Alnum());

任何实现Zend_Validate_Interface的对象都可以被用作校验器链。

标准校验类
Zend_Validate
Zend Framework手册 中文版
编写校验器
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Validate
  • 简介
  • 标准校验类
  • 校验器链
  • 编写校验器
  • Validation Messages


编写校验器 - Zend Framework Manual

校验器链
Zend_Validate
Zend Framework手册 中文版
Validation Messages

编写校验器

尽管提供了一组通用的校验器，但不可避免地，开发者还将为他们特定的需求来编写定制的校验器。编写定制的校验器的任务将在本节描述。

Zend_Validate_Interface 定义了三个方法，isValid()，getMessages() 和 getErrors(), 为了创建校验对象，它们可以在用户的类里被实现。实现Zend_Validate_Interface接口的对象可以用Zend_Validate::addValidator() 添加到校验链里。这样的对象也可以和Zend_Filter_Input一起使用。

也许你已经从上面关于 的描述中推断出，不论一个值是否被校验成功，校验类为Zend Framework返回一个布尔值。它们也提供关于why一个值校验失败的信息。校验失败原因的有效性对于不同用途的应用程序可能很有价值，象为可用性分析提供的统计量。

基本校验失败消息的功能在Zend_Validate_Abstract中实现。当创建一个校验类，简单地扩展Zend_Validate_Abstract来包括这个功能。在扩展类里你将实现isValid() 方法逻辑和定义消息变量和消息模板，它和可能发生的校验失败类型相对应。如果校验测试一个值失败，isValid() 应该返回 false。如果这个值通过校验测试，isValid() 应该返回 true。

一般地，isValid()方法不应该抛出任何异常，除了不可能决定输入值是否有效。一些抛出异常的合情合理的例子可能是如果文件不能被打开，LDAP服务器不能被联系，或者数据库连接无效，并且有些事情必须由校验成功或失败来决定。

Example #1 创建简单校验类

下面的例子演示如何编写一个非常简单的定制的校验器。在这个例子中，校验规则简单，输入值必须是浮点数值。

class MyValid_Float extends Zend_Validate_Abstract
{
    const FLOAT = 'float';

    protected $_messageTemplates = array(
        self::FLOAT => "'%value%' is not a floating point value"
    );

    public function isValid($value)
    {
        $this->_setValue($value);

        if (!is_float($value)) {
            $this->_error();
            return false;
        }

        return true;
    }
}
这个类为它的单个校验失败消息定义了一个模板，它包括内置的魔术参数，%value%。如果校验失败，对_setValue()的调用准备了自动插入被测试的值到失败消息的对象。对_error()的调用跟踪校验失败的原因。因为这个类只定义了一个失败消息，没有必要为_error()提供带有失败消息名字的模板。

Example #2 编写有独立条件的校验类

下面的例子演示一组稍微复杂的校验规则，要求输入值是数字并有最小值和最大值的范围。由于下面确切的原因之一，输入值校验失败：

  • 输入值不是数字。

  • 输入值小于允许的最小值。

  • 输入值大于允许的最大值。

这些校验失败的原因被翻译为在类中的定义：

class MyValid_NumericBetween extends Zend_Validate_Abstract
{
    const MSG_NUMERIC = 'msgNumeric';
    const MSG_MINIMUM = 'msgMinimum';
    const MSG_MAXIMUM = 'msgMaximum';

    public $minimum = 0;
    public $maximum = 100;

    protected $_messageVariables = array(
        'min' => 'minimum',
        'max' => 'maximum'
    );

    protected $_messageTemplates = array(
        self::MSG_NUMERIC => "'%value%' is not numeric",
        self::MSG_MINIMUM => "'%value%' must be at least '%min%'",
        self::MSG_MAXIMUM => "'%value%' must be no more than '%max%'"
    );

    public function isValid($value)
    {
        $this->_setValue($value);

        if (!is_numeric($value)) {
            $this->_error(self::MSG_NUMERIC);
            return false;
        }

        if ($value < $this->minimum) {
            $this->_error(self::MSG_MINIMUM);
            return false;
        }

        if ($value > $this->maximum) {
            $this->_error(self::MSG_MAXIMUM);
            return false;
        }

        return true;
    }
}
Public 属性$minimum 和 $maximum 分别为成功校验一个值被建立用来提供最小和最大值边界。这个类也定义了两个消息变量和public属性相对应并允许min 和 max 与 value 一起被用在作为魔术参数的消息模板，

注意如果任何在isValid()中的校验检查失败，一个恰当的失败消息被准备，并且方法立即返回false。这些校验规则因此继续独立。换句话说，如果一个测试失败，不需要测试任何后来的校验规则。然而这本来不是个案例。下面的例子示例如何编写带有独立校验规则的类，校验对象返回什么校验企图失败的。

Example #3 带有独立条件、多重失败原因的校验

考虑编写一个为密码加强强度的校验类－当用户被要求为帮助使用户账户安全而选择符合一定条件的密码。让我们假设口令安全条件加强那个密码：

  • 至少8个字符长，

  • 包括至少一个大写字母，

  • 包括至少一个小写字母，

  • 并至少包括一个数字字符。

下面的类实现这些校验条件：

class MyValid_PasswordStrength extends Zend_Validate_Abstract
{
    const LENGTH = 'length';
    const UPPER  = 'upper';
    const LOWER  = 'lower';
    const DIGIT  = 'digit';

    protected $_messageTemplates = array(
        self::LENGTH => "'%value%' must be at least 8 characters in length",
        self::UPPER  => "'%value%' must contain at least one uppercase letter",
        self::LOWER  => "'%value%' must contain at least one lowercase letter",
        self::DIGIT  => "'%value%' must contain at least one digit character"
    );

    public function isValid($value)
    {
        $this->_setValue($value);

        $isValid = true;

        if (strlen($value) < 8) {
            $this->_error(self::LENGTH);
            $isValid = false;
        }

        if (!preg_match('/[A-Z]/', $value)) {
            $this->_error(self::UPPER);
            $isValid = false;
        }

        if (!preg_match('/[a-z]/', $value)) {
            $this->_error(self::LOWER);
            $isValid = false;
        }

        if (!preg_match('/\d/', $value)) {
            $this->_error(self::DIGIT);
            $isValid = false;
        }

        return $isValid;
    }
}
注意在isValid()中的四个条件测试不立即返回false。这允许校验类提供所有的输入的密码不符合要求的原因。如果例如一个用户打算输入"#$%"字符串作为密码，isValid()将导致所有四个校验失败消息被后来的getMessages()调用返回。

校验器链
Zend_Validate
Zend Framework手册 中文版
Validation Messages
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Validate
  • 简介
  • 标准校验类
  • 校验器链
  • 编写校验器
  • Validation Messages


Validation Messages - Zend Framework Manual

编写校验器
Zend_Validate
Zend Framework手册 中文版
Zend_Version

Validation Messages

Each validator which is based on Zend_Validate provides one or multiple messages in the case of a failed validation. You can use this information to set your own messages, or to translate existing messages which a validator could return to something different.

These validation messages are constants which can be found at top of each validator class. Let's look into Zend_Validate_GreaterThan for an descriptive example:

  1. protected $_messageTemplates = array(
  2.     self::NOT_GREATER => "'%value%' is not greater than '%min%'",
  3. );

As you can see the constant self::NOT_GREATER refers to the failure and is used as key, and the message itself is used as value of the message array.

You can retrieve all message templates from a validator by using the getMessageTemplates() method. It returns you the above array which contains all messages a validator could return in the case of a failed validation.

  1. $validator = new Zend_Validate_GreaterThan();
  2. $messages  = $validator->getMessageTemplates();

Using the setMessage() method you can set another message to be returned in case of the specified failure.

  1. $validator = new Zend_Validate_GreaterThan();
  2. $validator->setMessage('Please enter a lower value', Zend_Validate_GreaterThan::NOT_GREATER);

The second parameter defines the failure which will be overridden. When you omit this parameter, then the given message will be set for all possible failures of this validator.

Using pre-translated validation messages

Zend Framework is shipped with more than 45 different validators with more than 200 failure messages. It can be a tendious task to translate all of these messages. But for your convinience Zend Framework comes with already pre-translated validation messages. You can find them within the path /resources/languages in your Zend Framework installation.

Note: Used path
 The resource files are outside of the library path because all of your translations should also be outside of this path.

So to translate all validation messages to german for example, all you have to do is to attach a translator to Zend_Validate using these resource files.

  1. $translator = new Zend_Translate(
  2.     'array',
  3.     '/resources/languages',
  4.     $language,
  5.     array('scan' => Zend_Locale::LOCALE_DIRECTORY)
  6. );
  7. Zend_Validate_Abstract::setDefaultTranslator($translator);

Note: Used translation adapter
 As translation adapter Zend Framework choosed the array adapter. It is simple to edit and created very fast.

Note: Supported languages
 This feature is very young, so the amount of supported languages may not be complete. New languages will be added with each release. Additionally feel free to use the existing resource files to make your own translations.
You could also use these resource files to rewrite existing translations. So you are not in need to create these files manually yourself.

Limit the size of a validation message

Sometimes it is necessary to limit the maximum size a validation message can have. For example when your view allows a maximum size of 100 chars to be rendered on one line. To simplify the usage, Zend_Validate is able to automatically limit the maximum returned size of a validation message.

To get the actual set size use Zend_Validate::getMessageLength(). If it is -1, then the returned message will not be truncated. This is default behaviour.

To limit the returned message size use Zend_Validate::setMessageLength(). Set it to any integer size you need. When the returned message exceeds the set size, then the message will be truncated and the string '...' will be added instead of the rest of the message.

  1. Zend_Validate::setMessageLength(100);

Note: Where is this parameter used?
 The set message length is used for all validators, even for self defined ones, as long as they extend Zend_Validate_Abstract.

编写校验器
Zend_Validate
Zend Framework手册 中文版
Zend_Version
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Validate
  • 简介
  • 标准校验类
  • 校验器链
  • 编写校验器
  • Validation Messages


Zend_Version - Zend Framework Manual

Validation Messages
Zend Framework Reference
Zend Framework手册 中文版
读取Zend Framework的当前版本

Zend_Version

Table of Contents
  • 读取Zend Framework的当前版本
Validation Messages
Zend Framework Reference
Zend Framework手册 中文版
读取Zend Framework的当前版本
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


读取Zend Framework的当前版本 - Zend Framework Manual

Zend_Version
Zend_Version
Zend Framework手册 中文版
Zend_View

读取Zend Framework的当前版本

常量Zend_Version::VERSION的值为Zend Framework的当前版本号，例如0.9.0beta。

静态方法Zend_Version::compareVersion($version)基于PHP函数» version_compare()。如果指定的$version比当前ZF的版本旧，则该方法返回-1，如果相等则返回0，如果比当前版本更新返回+1。

Example #1 compareVersion()方法示例：

// returns -1, 0 or 1
$cmp = Zend_Version::compareVersion('1.0.0');
Zend_Version
Zend_Version
Zend Framework手册 中文版
Zend_View
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Version
  • 读取Zend Framework的当前版本


Zend_View - Zend Framework Manual

读取Zend Framework的当前版本
Zend Framework Reference
Zend Framework手册 中文版
简介

Zend_View

Table of Contents
  • 简介
  • 控制器脚本
  • 视图脚本
  • 视图助手（View Helper）
  • Zend_View_Abstract
读取Zend Framework的当前版本
Zend Framework Reference
Zend Framework手册 中文版
简介
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


简介 - Zend Framework Manual

Zend_View
Zend_View
Zend Framework手册 中文版
控制器脚本

简介

Zend_View是用来在MVC模式中处理View（视图）部份的一个类。也就是说它用来使视图部份的代码与Model及controller部分分离。它提供了helper,output filter,variable escaping等几个功能组件。

Zend_View使用PHP本身作为你的模板，或者你也可以建立其它模板引擎的实例，并用你的view代码来对其进行操作。

使用Zend_View主要有两步： 1. 你的Controller建立一个Zend_View实例，并将需要的变量传递给它； 2. Controller告诉Zend_View解析一个特定的视图，生成View输出的内容。

控制器脚本

下面是一个简单的例子。假设你有一个书籍清单，想把它打印出来。控制器代码可能看起来是这样的：

<?php
//使用一个模型来获取书籍作者和标题相关数据。
$data = array(
    array(
        'author' => 'Hernando de Soto',
        'title' => 'The Mystery of Capitalism'
    ),
    array(
        'author' => 'Henry Hazlitt',
        'title' => 'Economics in One Lesson'
    ),
    array(
        'author' => 'Milton Friedman',
        'title' => 'Free to Choose'
    )
);

//传递数据给Zend_View类的实例
Zend_Loader::loadClass('Zend_View');
$view = new Zend_View();
$view->books = $data;

//解析一段View代码"booklist.php"来显示数据
echo $view->render('booklist.php');

视图脚本

现在我们看看相关的视图代码"booklist.php"。这是一段普通的代码，但是有一点特别：它是在Zend_View实例的内部运行的，所以$this指向的是Zend_View实例和类方法。(controller传递给Zend_View实例的变量是public的)。一段非常基本的视图代码看起来是这样的：

<?php if ($this->books): ?>

    <!-- 包含几本书信息的HTML表格. -->
    <table>
        <tr>
            <th>Author</th>
            <th>Title</th>
        </tr>

        <?php foreach ($this->books as $key => $val): ?>
        <tr>
            <td><?php echo $this->escape($val['author']) ?></td>
            <td><?php echo $this->escape($val['title']) ?></td>
        </tr>
        <?php endforeach; ?>

    </table>

<?php else: ?>

    <p>There are no books to display.</p>

<?php endif; ?>

注意我们使用escape()来转义输出。

选项

Zend_View有若干选项来配置视图脚本的运行。

  • basePath: 指示一个基本路径，可以在下面设置script、 helper 和 filter 路径。目录结构如下：

    base/path/
    helpers/
    filters/
    scripts/

    可以通过 setBasePath()、addBasePath()、或 basePath设置给构造器。

  • encoding: 指定 htmlentities()、htmlspecialchars()和其它操作所采用的字符集，缺省为 ISO-8859-1 (latin1)。也可以通过setEncoding() 或 encoding 设置给构造器。

  • escape: 指定escape()所使用的回调函数（callback）。也可以通过setEscape()或escape设置给构造器。

  • filter: 指示在解析视图脚本后使用的过滤器。可以通过setFilter()、addFilter()或者filter设置给构造器。

  • strictVars: 指定某些未初始化的视图变量被访问时，Zend_View必须发出通知和警告。可以通过调用strictVars(true) 或传递strictVars给构造器来设置。

实用访问器

一般来说，你只需要调用assign()、render()或其中之一来设置/添加过滤器、助手类、和脚本路径。然而，如果希望扩展Zend_View或需要访问它的内部，有许多访问器（Accessor）可用：

  • getVars() 将返回所有已赋值的变量。

  • clearVars() 将清除所有已赋值的变量；当你想重新使用同一个视图对象，并决定哪些变量可用时，这个功能很有用。

  • getScriptPath($script) 将获取指定的视图脚本的路径。

  • getScriptPaths() 将获取所有注册的脚本路径。

  • getHelperPath($helper) 将获取已命名的助手类的路径。

  • getHelperPaths() 将获取所有注册的助手路径。

  • getFilterPath($filter) 将获取已命名的过滤器类的路径。

  • getFilterPaths() 将获取所有注册的过滤器文件的路径。

Zend_View
Zend_View
Zend Framework手册 中文版
控制器脚本
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_View
  • 简介
  • 控制器脚本
  • 视图脚本
  • 视图助手（View Helper）
  • Zend_View_Abstract


控制器脚本 - Zend Framework Manual

简介
Zend_View
Zend Framework手册 中文版
视图脚本

控制器脚本

控制器是你实例化和配置Zend_View的地方。你可以分配变量给view，并让view使用某个特定的模板来输出。

变量赋值

控制器需要向视图传递必要的变量，在它处理view的代码之前。通常你可以一次一个地完成变量赋值的工作。

$view = new Zend_View();
$view->a = "Hay";
$view->b = "Bee";
$view->c = "Sea";

然而这样比较麻烦，那么你可以将它们放进一个数组或对象中去。assign()方法允许你通过数组或对象进行赋值。下面这个例子和上例（一次一个赋值）的结果是一样的：

$view = new Zend_View();

//以数组的形式进行赋值，键名为View的变量名，键值为变量值

$array = array(
    'a' => "Hay",
    'b' => "Bee",
    'c' => "Sea",
);
$view->assign($array);

//也可以通过对象来赋值，但要先把对象转型为数组
$obj = new StdClass;
$obj->a = "Hay";
$obj->b = "Bee";
$obj->c = "Sea";
$view->assign((array) $obj);

另外，你也可使用这样的方法： 第一个参数是变量名，第二个是变量的值。

$view = new Zend_View();
$view->assign('a', "Hay");
$view->assign('b', "Bee");
$view->assign('c', "Sea");

调用视图脚本并打印输出

完成所有变量赋值后，Controller通知Zend_View通过render()调用一段特定的视图代码。注意，这个方法将只返回处理后的视图，而不直接输出，所以你要用print或echo来打印输出。

$view = new Zend_View();
$view->a = "Hay";
$view->b = "Bee";
$view->c = "Sea";
echo $view->render('someView.php');

视图脚本的路径

默认地， Zend_View希望你的View脚本和Controller脚本在同一目录下。比如说，如果你的Controller文件在 “/path/to/app/controllers”目录下，并调用$view->render('someView.php')，则Zend_View会查找"/path/to/app/controllers/someVire.php"文件。

显然，你的View代码很可能放在其它地方，那么需要告诉 Zend_View去哪里找，可使用 setScriptPath()方法。

$view = new Zend_View();
$view->setScriptPath('/path/to/app/views');

现在当你调用$view->render('someView.php')，它会去找"/path/to/app/views/someView.php"。

事实上，你可以通过addScriptPath()增加路径。Zend_View会到最近增加的路径目录下找View脚本。这样你可以改变默认的外观，通过定制和使用自己的皮肤或主题。

$view = new Zend_View();
$view->addScriptPath('/path/to/app/views');
$view->addScriptPath('/path/to/custom/');

// 现在如果你调用 $view->render('booklist.php'), Zend_View 将
// 首先查找 "/path/to/custom/booklist.php", 找不到再找
// "/path/to/app/views/booklist.php", 如果还找不到，最后查找当前目录下//的"booklist.php".
简介
Zend_View
Zend Framework手册 中文版
视图脚本
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_View
  • 简介
  • 控制器脚本
  • 视图脚本
  • 视图助手（View Helper）
  • Zend_View_Abstract


视图助手（View Helper） - Zend Framework Manual

视图脚本
Zend_View
Zend Framework手册 中文版
Zend_View_Abstract

视图助手（View Helper）

在你的视图脚本中，经常需要执行某些特定的复杂的功能：例如，格式化日期，生成表单对象，或者显示action的链接等等。你可以使用助手类来完成这些工作。

助手就是简单的类。假设你想要一个名为'fooBar'的助手，缺省地，类的前缀是'Zend_View_Helper_' （当设定助手路径时，你可以指定定制的前缀），类名的最后一部分就是助手名称；这一部分应该是TitleCapped（即像英文文章的标题一样，例如fooBar就要写成FooBar，by Jason Qi）;所以，类的全名就是Zend_View_Helper_FooBar 。这个类应当至少有一个在助手之后命名的方法，并且是驼峰格式（即首字母小写，之后的每个单词首字母大写，例如thisIsAnExample。详见http://c2.com/cgi/wiki?CamelCase　-- Haohappy注）：fooBar() 。

Note: 注意大小写
助手名称总是遵循驼峰格式，例如，它们从不以大写字母开头。类名是混合大小写字格式，但方法在执行时是驼峰格式。

Note: 缺省助手路径
即使调用 setHelperPath() 来重写当前的路径，缺省助手路径总是指向 Zend Framework 视图助手， 例如：'Zend/View/Helper/'，设置这个路径来确保缺省的助手工作。

在视图脚本中，你可以用$this->helperName()来调用helper。这时Zend_View会加载 Zend_View_Helper_HelperName类，建立一个对象实例，并调用它的helperName()方法。对象的实例会在 Zend_View的实例内一直存在，并可以被$this->helperName()重复调用。

基本的助手

Zend_View自带了几个helper类，大部分是用来生成组件的和有自动转义变量的功能。另外，有些助手用来创建基于路由的URL和HTML列表以及声明变量。当前的助手包括：

  • declareVars(): 当使用 strictVars() 时很有用，这个助手可用来声明已经或还没有在View对象里设置的模板变量，并设置缺省值。当作参数传递改方法的数组将用来设置缺省值；否则，如果变量不存在，就设置一个空的字符串。

  • fieldset($name, $content, $attribs): 生成一个 XHTML fieldset. 如果 $attribs 包含一个 'legend' 键，它的值将用于 fieldset legend。 Fieldset 将环绕在 $content 周围提供给助手。

  • form($name, $attribs, $content): 生成一个 XHTML 表单。所有 $attribs 转义和解析成表单标签的 XHTML 属性。如果 $content 不以布尔 false 出现，那么内容就是在表单标签内被解析，如果 $content 是布尔 false （缺省），只有开头的表单标签被生成。

  • formButton($name, $value, $attribs): 生成 <button /> 元素;

  • formCheckbox($name, $value, $attribs,$options): 生成 <input type="checkbox" /> 元素。

    缺省地，当没有提供 $value 并且没有 $options，'0' 被假定为未选的值，'1'为选中的值。 如果传递 $value，但没有 $options，选中的值就被假定为传递的值。

    $options 应当是数组。如果数组被索引，第一个值就是选中的值，第二个是未选的值， 所有其它值被忽略。 你也可传递一个带有键为 'checked' 和 'unChecked' 的联合数组。

    如果传递了 $options，如果 $value 匹配选中的值，元素将标记为选中。你也通过传递 一个布尔值给属性 'checked' 来标记元素为选中或未选。

    上述内容可能最好汇总成一些例子：

    <?php
// '1' and '0' as checked/unchecked options; not checked
echo $this->formCheckbox('foo');

// '1' and '0' as checked/unchecked options; checked
echo $this->formCheckbox('foo', null, array('checked' => true));

// 'bar' and '0' as checked/unchecked options; not checked
echo $this->formCheckbox('foo', 'bar');

// 'bar' and '0' as checked/unchecked options; checked
echo $this->formCheckbox('foo', 'bar', array('checked' => true));

// 'bar' and 'baz' as checked/unchecked options; unchecked
echo $this->formCheckbox('foo', null, null, array('bar', 'baz');

// 'bar' and 'baz' as checked/unchecked options; unchecked
echo $this->formCheckbox('foo', null, null, array(
    'checked' => 'bar',
    'unChecked' => 'baz'
));

// 'bar' and 'baz' as checked/unchecked options; checked
echo $this->formCheckbox('foo', 'bar', null, array('bar', 'baz');
echo $this->formCheckbox('foo', null, array('checked' => true), array('bar', 'baz');

// 'bar' and 'baz' as checked/unchecked options; unchecked
echo $this->formCheckbox('foo', 'baz', null, array('bar', 'baz');
echo $this->formCheckbox('foo', null, array('checked' => false), array('bar', 'baz');

    对所有情况，标记预先准备一个带有未选的值的隐藏元素。 这样，如果值是未选的，你将仍获得有效的返回到表单的值。

  • formErrors($errors, $options): 生成一个无顺序的 XHTML 列表来显示错误。 $errors 是个字符串或字符串数组；$options 是你想放入开头列表标签的任何属性。

    当通过调用助手中的方法时，你可以指定替代的开头，结尾和分隔符：

    • setElementStart($string); 缺省为 '<ul class="errors"%s"><li>', 其中 %s 是在 $options 中被替换的属性。

    • setElementSeparator($string); 缺省为 '</li><li>'。

    • setElementEnd($string); 缺省为 '</li></ul>'。

  • formFile($name, $value, $attribs): 生成<input type="file" />

  • formHidden($name, $value, $attribs): 生成<input type="hidden" />

  • formLabel($name, $value, $attribs): 生成 <label>设置 for 属性给 $name，实际的标签字符给 $value。 如果 disable 传递给 attribs，什么都不返回。

  • formMultiCheckbox($name, $value, $attribs, $options, $listsep): 生成一个 checkboxes 列表。$options 是个联合数组，可以有任意的深度。$value 可以是单个的值或者是可选的匹配在 $options 数组中的键的一个数组。$listsep 缺省为一个 HTML break ("<br />")。缺省地，这个元素被当作数组，所有 checkboxes 共享同一个名称，并以数组的形式提交。

  • formPassword($name, $value, $attribs): Creates an <input type="password" /> element.

  • formRadio($name, $value, $attribs, $options): 生成一系列<input type="button" />，每个$options数组元素一个，key为radio的值，并且元素的值是radio的标签。

  • formReset($name, $value, $attribs): 生成<input type="reset" />

  • formSelect($name, $value, $attribs, $options): 生成<select>...</select>其中的每个<option>对应于一个$option数组元素。元素的key是option的值，元素的值是option的标签。$value这个值的option默认为选中。

  • formSubmit($name, $value, $attribs): 生成<input type="submit" />

  • formText($name, $value, $attribs): 生成<input type="text" />

  • formTextarea($name, $value, $attribs): 生成<textarea>...</textarea>

  • url($urlOptions, $name, $reset): 基于已命名的路由生成URL字符串。$urlOptions 必须是一个键/值对应的关联数组，用于特定的路由。

  • htmlList($items, $ordered, $attribs): 基于传递给它的 $items 生成无序的和有序的列表。如果 $items 是多维数组，将创建嵌套的列表。

以上helper的使用非常简单，下面是个例子。注意你只需要调用即可，它们会根据需要自己加载并实例化。

<?php
// 在你的view脚本内部, $this 指向 Zend_View 实例.
//
// 假设你已经为select对应的变量$countries指定一系列option值，
// array('us' => 'United States', 'il' =>
// 'Israel', 'de' => 'Germany').
?>
<form action="action.php" method="post">
    <p><label>Your Email:
        <?php echo $this->formText('email', 'you@example.com', array('size' => 32)) ?>
    </label></p>
    <p><label>Your Country:
        <?php echo $this->formSelect('country', 'us', null, $this->countries) ?>
    </label></p>
    <p><label>Would you like to opt in?
        <?php echo $this->formCheckbox('opt_in', 'yes', null, array('yes', 'no')) ?>
    </label></p>
</form>

以上视图脚本会输出这样的结果：

<form action="action.php" method="post">
    <p><label>Your Email:
        <input type="text" name="email" value="you@example.com" size="32" />
    </label></p>
    <p><label>Your Country:
        <select name="country">
            <option value="us" selected="selected">United States</option>
            <option value="il">Israel</option>
            <option value="de">Germany</option>
        </select>
    </label></p>
    <p><label>Would you like to opt in?
        <input type="hidden" name="opt_in" value="no" />
        <input type="checkbox" name="opt_in" value="yes" checked="checked" />
    </label></p>
</form>

动作视图助手

Action 视图助手允许视图脚本执行一个特定的控制器Action；在执行之后的响应对象的结果将被返回。有时候特定的Action生成可重用内容或“widget-ized”内容（在页面内生成一个带有特定功能的小面板，类似于Windows Vista的widget，Haohappy注），这时我们就可以使用本功能。

内部调用_forward() 或者转向的Action在此将无效，将返回空字符串。

Action视图助手的API和大部分MVC组件调用控制器动作的方式一样：action($action,$controller, $module = null, array $params = array())。$action 和 $controller 是必须的；如果没有指定模块，缺省模块将被使用。

Example #1 动作视图助手的基本用法

例如，假设你有一个CommentController ，为了给当前请求输出评论列表，带一个可被调用的 listAction() 方法：

<div id="sidebar right">
    <div class="item">
        <?= $this->action('list', 'comment', null, array('count' => 10)); ?>
    </div>
</div>

区域助手（Partial Helper）

Partial 视图助手被用来在它自己的变量范围内解析特定的模板。主要用法是（解析）可重用的模板片段，你不需要操心变量名的冲突。另外，它们让你从特定的模块指定 partial 视图脚本。

Partial 的兄弟 PartialLoop 视图助手允许传递可迭代数据并为每个条目解析一部分。

Example #2 Partials 的基本用法

partials 的基本用法是在它自己的视图范围内解析一个模板的片段。

<?php // partial.phtml ?>
<ul>
    <li>From: <?= $this->escape($this->from) ?></li>
    <li>Subject: <?= $this->escape($this->subject) ?></li>
</ul>

你可以这样从视图脚本里调用它：

<?= $this->partial('partial.phtml', array(
    'from' => 'Team Framework',
    'subject' => 'view partials')); ?>

解析结果如下：

<ul>
    <li>From: Team Framework</li>
    <li>Subject: view partials</li>
</ul>

Note: 什么是模型（model）?
和 Partial 视图助手一起使用的模型（即partial()的第二个参数，Haohappy注）可以是下列其中之一：

  • 数组 。如果传递了数组，它应当是联合数组，因为它的 ‘键/值’ 对用作为视图变量的键赋值给视图。

  • 实现了toArray() 方法的对象 。如果被传递的对象有 toArray() 方法，toArray()的结果将被当作视图变量赋值给视图对象。

  • 标准对象 。 任何其它对象将把object_get_vars()的结果（对象的所有公共属性）赋值给视图对象。

如果你的模型是一个对象，你可能想让它作为对象传递给 partial 脚本，而不是把它系列化成一个数组变量。 你可以通过设置适当的助手的 'objectKey' 属性来完成这个：
// Tell partial to pass objects as 'model' variable
$view->partial()->setObjectKey('model');

// Tell partial to pass objects from partialLoop as 'model' variable in final
// partial view script:
$view->partialLoop()->setObjectKey('model');
当传递 Zend_Db_Table_Rowsets 给 partialLoop()时这个技术相当有用， 因为你在视图脚本里有全部访问 row 对象的权限，允许你调用它们的方法（如从父或依赖的 rows 获取数据）。

Example #3 使用 PartialLoop 来解析可迭代的（Iterable）的模型

可能你常常会需要在一个循环里使用 partials 来输出相同的内容片段多次，这时你就可以把大块的重复的内容或复杂的显示逻辑放到一个地方。然而这对性能有影响，因为partial助手需要在每个迭代里调用一次。

PartialLoop 视图助手解决了这个问题。 它允许你把迭代条目（实现Iterator的数组或对象）当做模型来传递。它这些把这些条目当作模型迭代、传递给 partial 脚本。在迭代器里的条目可以是 Partial 视图助手允许的任何模型。

让我们看一下下面的 partial 视图脚本：

<? // partialLoop.phtml ?>
    <dt><?= $this->key ?></dt>
    <dd><?= $this->value ?></dd>

添加下列 "model"：

<?php
$model = array(
    array('key' => 'Mammal', 'value' => 'Camel'),
    array('key' => 'Bird', 'value' => 'Penguin'),
    array('key' => 'Reptile', 'value' => 'Asp'),
    array('key' => 'Fish', 'value' => 'Flounder'),
);
?>

在视图脚本中，你可以这样调用 PartialLoop 助手：

<dl>
<?= $this->partialLoop('partialLoop.phtml', $model) ?>
</dl>

<dl></dl>
    <dt>Mammal</dt>
    <dd>Camel</dd>

    <dt>Bird</dt>
    <dd>Penguin</dd>

    <dt>Reptile</dt>
    <dd>Asp</dd>

    <dt>Fish</dt>
    <dd>Flounder</dd>

</dl>

Example #4 在其它模块中解析 Partials

有时候 partial 存在于不同的模块(Module)。如果你知道模块的名称，你可以把它当作第二个参数传递给 partial() 或者 partialLoop()，把 $model 作为第三个参数。

例如，如果一个你想用一个在 'list' 模块的 pager partial，就象下面这样来运用：

<?= $this->partial('pager.phtml', 'list', $pagerData) ?>

这样，你可以重用原来是特别供给其它模块使用的 partials 。所以，在共享的视图脚本路径里放置可重用的 partials 很可能是个好习惯。

占位符助手（Placeholder Helper）

Placeholder 视图助手用来在视图脚本和视图实例之间持久化内容。它也提供一些有用的功能如：聚合内容、抓取视图脚本内容以后来用和添加前置（pre-）和后置（post-）文本到内容 （还可以为聚合内容定制分隔符等）。

Example #5 占位符的基本用法

占位符的基本用法是将视图中的数据持久化。每个Placeholder助手的启用都需要一个占位符名称，助手接着返回一个占位符容器对象，你可以用来处理或者简单地输出。

<?php $this->placeholder('foo')->set("Some text for later") ?>

<?php
    echo $this->placeholder('foo');
    // outputs "Some text for later"
?>

Example #6 用占位符来聚合内容

通过占位符来聚合内容有时候很有用。例如视图脚本可拥有一个变量数组来存放数据，而视图脚本可以决定这些数据如何显示出来。

Placeholder 视图助手使用继承自 ArrayObject 的容器，为处理数组提供了丰富的功能。另外，它为格式化存储在容器里的内容提供了众多的方法：

  • setPrefix($prefix) 用内容的前缀设置文本。任何时候使用 getPrefix() 来确定当前的设置是什么。

  • setPostfix($prefix) 用要追加的内容设置文本。任何时候使用 getPostfix() 来确定当前的设置是什么。

  • setSeparator($prefix) 设置用来分隔聚合内容的分隔符。任何时候使用 getSeparator() 来确定当前的设置是什么。

  • setIndent($prefix) 可以用来给内容设置一个缩进的值。如果传递一个整数，就按这个数量来缩进；如果传递一个字符串，就按字符串的长度来缩进。任何时候使用 getIndent() 来确定当前的设置是什么。

<!-- first view script -->
<?php $this->placeholder('foo')->exchangeArray($this->data) ?>

<!-- later view script -->
<?php
$this->placeholder('foo')->setPrefix("<ul>\n    <li>")
                         ->setSeparator("</li><li>\n")
                         ->setIndent(4)
                         ->setPostfix("</li></ul>\n");
?>

<?php
    echo $this->placeholder('foo');
    //输出一个带有漂亮缩进的HTML无序列表
?>

因为 Placeholder 容器对象从 ArrayObject 继承而来，所以你可以很容易地给特定的键赋值，而不是简单地把它压进容器。键可以作为对象属性或数组键来访问。

<?php $this->placeholder('foo')->bar = $this->data ?>
<?php echo $this->placeholder('foo')->bar ?>

<?php
$foo = $this->placeholder('foo');
echo $foo['bar'];
?>

Example #7 使用占位符（Placeholders）来抓取内容

有时你可能会在视图脚本（最容易的模板）为占位符放些内容，Placeholder 视图助手允许你抓取任意的内容，在以后用下列的 API 来解析并输出（本功能类似于缓冲输出－－Haohappy注）：

  • captureStart($type, $key) 开始抓取内容。

    $type 应该是 Placeholder 的常量 APPEND 或 SET 其中之一。如果用 APPEND，被抓取得内容就追加到在占位符当前内容的列表； 如果用 SET，被抓取得内容就被用作占位符的唯一内容（替换以前的内容）。缺省地 $type 是 APPEND。

    $key可用来在占位符容器指定一个特殊的键给你想抓取的内容。

    captureStart() 锁住抓取直到 captureEnd() 被调用，不能在同一个占位符容器里嵌套抓取，这样做会引起一个异常。

  • captureEnd() 使抓取内容停止，并根据 captureStart() 如何被调用来把它放到容器对象。

<!-- Default capture: append -->
<?php $this->placeholder('foo')->captureStart();
foreach ($this->data as $datum): ?>
<div class="foo">
    <h2><?= $datum->title ?></h2>
    <p><?= $datum->content ?></p>
</div>
 <?php endforeach; ?>
<?php $this->placeholder('foo')->captureEnd() ?>

<?php echo $this->placeholder('foo') ?>

<!-- Capture to key -->
<?php $this->placeholder('foo')->captureStart('SET', 'data');
foreach ($this->data as $datum): ?>
<div class="foo">
    <h2><?= $datum->title ?></h2>
    <p><?= $datum->content ?></p>
</div>
 <?php endforeach; ?>
<?php $this->placeholder('foo')->captureEnd() ?>

<?php echo $this->placeholder('foo')->data ?>

具体占位符实现

Zend Framework 自带有若干个具体实现的占位符，包括常用的占位符：doctype、page title、以及各种 <head> 元素。对所有情况，不带参数调用占位符将返回元素自己。

每个元素的文档，请查看如下链接：

  • Doctype

  • HeadLink

  • HeadMeta

  • HeadScript

  • HeadStyle

  • HeadTitle

  • InlineScript

文档类型助手（Doctype Helper）

有效的HTML和XHTML文档应当包括一个 DOCTYPE 声明。但是文档类型声明很难记忆，而且会影响到文档中的特定元素的解析（例如，在 <script> 和 <style> 元素中转义的CDATA）。

Doctype 助手允许指定下列类型之一：

  • XHTML11

  • XHTML1_STRICT

  • XHTML1_TRANSITIONAL

  • XHTML1_FRAMESET

  • XHTML_BASIC1

  • HTML4_STRICT

  • HTML4_LOOSE

  • HTML4_FRAMESET

你也可以指定一个自己定制的带有良好结构的文档类型。

Doctype助手是 占位符助手 的一个具体的实现。

Example #8 Doctype 助手的基本用法

在任何时候都可以指定 doctype。然而，依赖 doctype 输出的助手只在你设置后才认识它，所以最简单的用法是在 bootstrap 脚本中指定：

$doctypeHelper = new Zend_View_Helper_Doctype();
$doctypeHelper->doctype('XHTML1_STRICT');

然后在布局脚本中输出：

<?php echo $this->doctype() ?>

Example #9 获取 Doctype

如果需要知道文档类型，可以在由调用助手返回的对象中调用getDoctype()。

<?php
$doctype = $view->doctype()->getDoctype();
?>

很常见地，你需要知道doctype是否XHTML；那么，isXhtml()方法已经足够：

<?php
if ($view->doctype()->isXhtml()) {
    // do something differently
}
?>

HeadLink 助手

HTML的 <link> 标签越来越多地用于为你的站点链接不同资源：stylesheet, feed, favicon, trackback等。HeadLink 助手提供了一个简单的接口用来创建和聚合这些元素以供稍后在你的布局脚本里获取和输出。

HeadLink 助手有以下特殊的方法用来添加 stylesheet 链接：

  • appendStylesheet($href, $media, $conditionalStylesheet)

  • offsetSetStylesheet($index, $href, $media, $conditionalStylesheet)

  • prependStylesheet($href, $media, $conditionalStylesheet)

  • setStylesheet($href, $media, $conditionalStylesheet)

$media 值缺省为 'screen'，但可以为任何有效的媒体(media)值。$conditionalStylesheet 是布尔值，将用于解析时来决定是否有特殊的注释应该被包括以防止在特定的平台上加载stylesheet。

另外，HeadLink 助手有特殊的方法用来添加 'alternate' 链接到它的堆栈：

  • appendAlternate($href, $type, $title)

  • offsetSetAlternate($index, $href, $type, $title)

  • prependAlternate($href, $type, $title)

  • setAlternate($href, $type, $title)

headLink() 助手方法允许指定所有的必要的属性给 <link> 元素， 也允许指定替代 － 是否新元素替换所有其他的，前置（栈顶），或追加（栈底）。

HeadLink 助手是 占位符助手 的一个具体实现。

Example #10 HeadLink 助手的基本用法

任何时候可以指定headLink，典型地，将在布局脚本里指定全局链接，并在应用程序视图脚本里指定特定的链接。在布局脚本里的 <head> 部份，用echo来输出。

<?php // 在视图脚本中设置链接：
$this->headLink()->appendStylesheet('/styles/basic.css')
                 ->headLink(array('rel' => 'favicon', 'href' => '/img/favicon.ico'), 'PREPEND')
                 ->prependStylesheet('/styles/moz.css', 'screen', true);
?>
<?php // 解析链接：?>
<?= $this->headLink() ?>

HeadMeta 助手

HTML <meta>元素用来提供关于HTML文档的 meta 信息－如关键字，文档字符集，缓冲的 pragama 等。Meta标签可以是'http-equiv' 或 'name' 类型，必须包含'content'属性，并且也可以有 'lang' 或 'scheme' 修饰属性。

HeadMeta 助手提供下列方法来设置和添加 meta 标签：

  • appendName($keyValue, $content, $conditionalName)

  • offsetSetName($index, $keyValue, $content, $conditionalName)

  • prependName($keyValue, $content, $conditionalName)

  • setName($keyValue, $content, $modifiers)

  • appendHttpEquiv($keyValue, $content, $conditionalHttpEquiv)

  • offsetSetHttpEquiv($index, $keyValue, $content, $conditionalHttpEquiv)

  • prependHttpEquiv($keyValue, $content, $conditionalHttpEquiv)

  • setHttpEquiv($keyValue, $content, $modifiers)

$keyValue 参数用来定义'name'的值或'http-equive'键；$content 是'content' 键的值，$modifiers 是可选的包含'lang' 和/或 'scheme'键的联合数组。

也可以用 headMeta() 助手方法来设置 meta 标签：headMeta($content, $keyValue, $keyType = 'name', $modifiers = array(), $placement = 'APPEND')。$keyValue 是指定在 $keyType 里的键的内容，$keyType 应该是'name' 或 'http-equiv'。$placement 可以是 'SET' （覆盖所有先前存储的值）， 'APPEND' （添加到栈尾）或 'PREPEND'（添加到栈顶）。

HeadMeta 覆盖每个 append()、offsetSet()、 prepend() 和 set() 来加强上面列出的特殊方法的用法。在内部，它存储每个条目为 stdClass 令牌，它稍后用 itemToString() 方法来序列化。这允许在堆栈的条目中执行检查，并可选地通过修改对象返回来修改这些条目。

HeadMeta助手是 占位符助手 的一个具体实现。

Example #11 HeadMeta 助手基本用法

你可以在任何时候指定一个新的meta标签。例如指定客户端缓冲规则或SEO关键字。

例如，如果想指定SEO关键字，要创建带有名为'keywords'和内容（在页面上和关键字有关联的）的meta名称标签：

<?php // setting meta keywords
$this->headMeta()->appendName('keywords', 'framework php productivity');
?>

如果想设置一些客户端缓冲规则，最好设置带有想执行的规则的 http-equiv 标签：

<?php // 禁止客户端缓存
$this->headMeta()->appendHttpEquiv('expires', 'Wed, 26 Feb 1997 08:21:57 GMT')
                 ->appendHttpEquiv('pragma', 'no-cache')
                 ->appendHttpEquiv('Cache-Control', 'no-cache');
?>

meta标签的另一个流行用法是设置内容类型，字符集和语言：

<?php // setting content type and character set
$this->headMeta()->appendHttpEquiv('Content-Type', 'text/html; charset=UTF-8')
                 ->appendHttpEquiv('Content-Language', 'en-US');
?>

最后一个例子，可以使用"meta refresh" 来让页面转向，一个简单的办法来显示过渡消息：

<?php // 设置以下meta可使页面3秒钟后转向一个新的url
$this->headMeta()->appendHttpEquiv('Refresh', '3;URL=http://www.some.org/some.html');
?>

在布局脚本(layout)中放置所有meta标签后，简单地echo助手，把所有内容输出：

<?= $this->headMeta() ?>

HeadScript 助手

HTML <script> 元素用来提供内嵌的客户端脚本元素或链接到远程包含客户端脚本代码的资源。你可以用HeadScript 助手来管理它们。

HeadScript 助手支持下列方法来设置和添加脚本：

  • appendFile($src, $type = 'text/javascript', $attrs = array())

  • offsetSetFile($index, $src, $type = 'text/javascript', $attrs = array())

  • prependFile($src, $type = 'text/javascript', $attrs = array())

  • setFile($src, $type = 'text/javascript', $attrs = array())

  • appendScript($script, $type = 'text/javascript', $attrs = array())

  • offsetSetScript($index, $script, $type = 'text/javascript', $attrs = array())

  • prependScript($script, $type = 'text/javascript', $attrs = array())

  • setScript($script, $type = 'text/javascript', $attrs = array())

对于所有*File()方法，$src 是要加载的脚本的远程位置，常常以 URL 或路径的形式表示。 对于所有*Script()方法，$script是客户端你想用于元素中的脚本。

HeadScript也允许抓取脚本，然后放到其它地方，如果你想通过程序生成客户端脚本，这将很有用。下面的例子里有它的用法。

最后，你也可以用 headScript()方法 来快速地添加脚本元素，它的用法是： headScript($mode = 'FILE', $spec, $placement = 'APPEND')。$mode 是指链接一个文件还是一个脚本，可以是'FILE' 或 'SCRIPT' ，$spec 是链接的脚本文件或脚本代码。$placement必须为'APPEND', 'PREPEND', 或'SET'其中之一.

HeadScript 覆盖 append()， offsetSet()，prepend() 和 set() 中的每一个来加强上述特殊方法的用法。在内部，它存储每个条目为 stdClass 令牌，它在稍后用 itemToString() 方法 serializes 。这允许在堆栈里检查条目，并可选地通过修改返回的对象来修改这些条目。

The HeadScript 助手是 占位符助手 的一个具体实现。

Note: 在HTML Body中使用 InlineScript
当包含脚本内嵌在 HTML body里时，应当使用HeadScript 的兄弟助手，InlineScript。为了加速页面的加载，提高用户访问速度，特别是当使用第三方分析脚本（比如Google Analytics等流量统计系统的javascript文件 --Haohappy注），把脚本放在文档的最后是一个好的习惯。

Note: 任意的属性缺省关闭 （Disabled）
 缺省地，HeadScript 将只解析（render）由 W3C 赋予的 <script> 属性，包括 'type'、 'charset'、 'defer'、 'language' 和 'src' 。 然而，一些 javascript 框架，如 » Dojo，利用定制的属性来修改行为。为了允许这样的属性，可以通过 setAllowArbitraryAttributes() 方法来打开（enable）它们：

<?php
$this->headScript()->setAllowArbitraryAttributes(true);
?>

Example #12 HeadScript 助手基本用法

在任何时候可以指定一个新的脚本。如上所述，可以链接到外部资源文件或脚本自己。

<?php // adding scripts
$this->headScript()->appendFile('/js/prototype.js')
                   ->appendScript($onloadScript);
?>

在客户端脚本编程中，顺序常常很重要，因为依赖的缘故，需要确保按特定的顺序来加载库，使用 append、 prepend 和 offsetSet 指令来帮助完成任务：

<?php // 按顺序放置脚本文件

//设置偏移量来确保这个文件最后加载
$this->headScript()->offsetSetScript(100, '/js/myfuncs.js');

//使用scriptaculous效果文件，这时append动作使用索引101，接上行代码的索引
$this->headScript()->appendScript('/js/scriptaculous.js');

//但总是保证prototype文件首先加载
$this->headScript()->prependScript('/js/prototype.js');
?>

当准备好输出所有脚本到布局脚本，简单地 echo 这个助手：

<?= $this->headScript() ?>

Example #13 Capturing Scripts Using the HeadScript Helper

有时候，需要“编程式”地生成客户端脚本。你可以使用字符串串联、heredoc或类似的技术（字符串串联即$string1.$string2这种形式，heredoc即使用<<<操作符－－Haohappy注），通常通过创建脚本和在PHP标签里做手脚会更容易些。HeadScript 可以实现这个功能，把一段JavaScript代码抓取到堆栈中暂存（道理同缓冲输出－－Haohappy注）：

<?php $this->headScript()->captureStart() ?>
var action = '<?= $this->baseUrl ?>';
$('foo_form').action = action;
<?php $this->headScript()->captureEnd() ?>

下面是上例中的一些假设：

  • 脚本将追加到堆栈。如果需要替换或者追加到堆栈顶部，那么需要分别把 'SET' 或 'PREPEND' 作为第一个参数传递给 captureStart() 。

  • 脚本 MIME 类型假定为 'text/javascript'，如果想指定一个不同的类型，需要把它作为第二个参数传递给 captureStart() 。

  • 如果需要为 <script> 标签指定附加属性， 把它们放入数组作为第三个参数传递给 captureStart() 。

HeadStyle 助手

在 HTML <head> 元素中 HTML <style> 元素用来包含 CSS stylesheets inline 。

Note: 使用 HeadLink 来链接 CSS 文件
HeadLink 为包含外部 stylesheets 应该用来生成 <link> 元素。如果想定义自己的 stylesheets inline， 使用 HeadScript 。

HeadStyle 助手支持下列方法来设置和添加 stylesheet 声明：

  • appendStyle($content, $attributes = array())

  • offsetSetStyle($index, $content, $attributes = array())

  • prependStyle($content, $attributes = array())

  • setStyle($content, $attributes = array())

对于所有情况，$content 是实际上的 CSS 声明。$attributes 是提供给 style 标签的任何额外的属性：lang、 title、 media 或 dir 都是允许的。

HeadStyle 也允许抓取样式声明，如果想用程序生成声明，然后在任何地方自由使用，这很有用。这个用法将在下面的例子给出。

最后，你也可以用 headStyle()方法 来快速地添加声明元素，它的用法： headStyle($content$placement = 'APPEND', $attributes = array()) 。$placement 是 'APPEND'、 'PREPEND' 或 'SET'。

HeadStyle 覆盖 append()， offsetSet()，prepend() 和 set() 中的每一个来加强上述特殊方法的用法。 在内部，它存储每个条目为 stdClass 令牌，它在稍后用 itemToString() 方法 serializes 。这允许在堆栈里检查条目，并可选地通过修改返回的对象来修改这些条目。

HeadStyle 助手是 占位符助手 的一个具体实现。

Example #14 HeadStyle 助手的基本用法

在任何时候都可以指定一个新的样式标签：

<?php // adding styles
$this->headStyle()->appendStyle($styles);
?>

对 CSS 来说，顺序非常重要，因为层叠的顺序(the order of the cascade)，你需要确保样式表中的声明按特定的顺序加载。使用append、 prepend 和 offsetSet 指令可帮助你达到目的：

<?php // Putting styles in order

// place at a particular offset:
$this->headStyle()->offsetSetStyle(100, $customStyles);

// place at end:
$this->headStyle()->appendStyle($finalStyles);

// place at beginning
$this->headStyle()->prependStyle($firstStyles);
?>

当准备好在布局脚本里输出所有样式声明，简单地 echo 助手：

<?= $this->headStyle() ?>

Example #15 用 HeadStyle 助手抓取样式声明

有时候需要用程序生成 CSS 样式声明。当你可以使用字符串串联，heredoc等等， 通常通过创建脚本和在PHP标签里做手脚会更容易些。HeadStyle 可以做这个，把它抓取到堆栈：

<?php $this->headStyle()->captureStart() ?>
body {
    background-color: <?= $this->bgColor ?>;
}
<?php $this->headStyle()->captureEnd() ?>

下面是一些假设：

  • 样式声明将追加到堆栈。如果需要替换或者加到堆栈顶部，那么需要分别把 'SET' 或 'PREPEND' 作为第一个参数传递给 captureStart() 。

  • 如果想指定任何另外的属性给 <style> 标签，通过数组把它们作为第二个参数传递给 captureStart() 。

HeadTitle 助手

HTML <title> 元素用来提供标题给HTML文档。HeadTitle 助手允许用程序生成和存储标题供以后解析和输出。

HeadTitle 助手是 占位符助手 的一个具体实现。 它覆盖 toString() 方法来确保生成 <title> 元素，并添加一个 headTitle() 方法来快速并容易地设置和标题元素的聚合。那个方法的 signature 是 headTitle($title, $setType = 'APPEND')，缺省地是追加到堆栈（聚合标题元素）的值，但你也可以指定 'PREPEND' ( 放栈顶 ) 或 'SET' ( 重写堆栈 )。

Example #16 HeadTitle 助手基本用法

你可以在任何时候指定一个标题标签。一般的用法可以让你在应用程序的每一个层次来设置标题段：站点、控制器、动作和潜在的资源。

<?php
// setting the controller and action name as title segments:
//把控制器和动作的名称设置为标题的一部分
$request = Zend_Controller_Front::getInstance()->getRequest();
$this->headTitle($request->getActionName())
     ->headTitle($request->getControllerName());

// setting the site in the title; possibly in the layout script:
//添加标题内容，这种写法常用于布局脚本中
$this->headTitle('Zend Framework');

// setting a separator string for segments:
//为标题的各部分设置分隔符
$this->headTitle()->setSeparator(' / ');
?>

在布局脚本中准备好标题后，使用echo即可输出：

<!-- renders <action> / <controller> / Zend Framework -->
<?= $this->headTitle() ?>

HTML 对象助手

HTML <object> 元素在网页里用于嵌入媒体如 Flash 或 QuickTime。 对象视图助手用最小的代价来帮助嵌入媒体。

有四个初始的对象助手：

  • formFlash 为嵌入 Flash 文件生成 markup。

  • formObject 为嵌入定制对象生成 markup。

  • formPage 为嵌入其它 (X)HTML 页面生成 markup。

  • formQuicktime 为嵌入 QuickTime 文件生成 markup。

所有这些助手使用相似的接口。这样，本文档只包含两个助手的例子。

Example #17 Flash 助手

使用助手嵌入 Flash 到你的页面相当简单。唯一需要的参数是资源 URI。

<?php echo $this->htmlFlash('/path/to/flash.swf'); ?>

它输出下列 HTML:

<object data="/path/to/flash.swf" type="application/x-shockwave-flash"
    classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
    codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab">
</object>

另外你可以指定可以和 <object> 一起解析的属性、参数和内容。 这个用 htmlObject 助手来示范。

Example #18 通过传递另外的参数来定制对象

对象助手里的第一个参数总是必需的，它是你想嵌入的资源的 URI。 第二个参数只对 htmlObject 助手是必需的，其它助手对这个参数已经有了正确的值。 第三个参数用来传递属性到对象元素，它只接受带有key-value对的数组，classid 和 codebase 是这个属性的例子。 第四个参数也用带有key-value对的数组并用它们生成 <param> 元素，你将很快看到一个这样的例子。 最后一个是提供另外的内容给对象的选项。来看一下使用所有参数的例子。

echo $this->htmlObject(
    '/path/to/file.ext',
    'mime/type',
    array(
        'attr1' => 'aval1',
        'attr2' => 'aval2'
    ),
    array(
        'param1' => 'pval1',
        'param2' => 'pval2'
    ),
    'some content'
);

/*
这将输出:

<object data="/path/to/file.ext" type="mime/type"
    attr1="aval1" attr2="aval2">
    <param name="param1" value="pval1" />
    <param name="param2" value="pval2" />
    some content
</object>
*/

InlineScript 助手

HTML <script> 标签用来提供内嵌的客户端脚本，或者链接到远程包含客户端脚本代码的资源。InlineScript 助手允许你管理这两者。它由HeadScript派生，并且HeadScript助手的任何方法都可用，唯一不同的是需要用 inlineScript() 方法代替 headScript()。

Note: 在 HTML Body 里脚本使用 InlineScript
如果想在HTML body里内嵌脚本，应当使用 InlineScript 。为了加快页面加载速度（特别是使用第三方分析脚本时），把脚本放到文档的尾部是个很好的习惯。
一些 JS 库必须包含在 HTML head部分，对于这些类库请使用 HeadScript 。

JSON 助手

当创建返回 JSON 的视图，设置适当的响应头也非常重要，JSON 视图助手就是来做这个的。另外，缺省地，它关闭（disable）了布局（如果布局是打开（enable）的），因为布局一般不和 JSON 响应一起使用。

JSON 助手设置下列的头：

Content-Type: application/json

当解析响应来决定如何处理内容，大部分 AJAX 库寻找这个头。

JSON 助手的用法相当简单：

<?php
<?= $this->json($this->data) ?>
?>

翻译助手

通常，网站支持多种语言。使用 Zend 翻译 来翻译网站的内容并且 使用 翻译 视图助手来在视图里集成 Zend 翻译 。

在下面所有的例子里我们使用简单的数组翻译适配器（Array Translation Adapter）。当然你也可以使用任何 Zend_Translate 的实例和 Zend_Translate_Adapter 的任何子类。有若干方法来实例化 翻译 视图助手：

  • 已注册的，通过先前注册的实例

  • 后来地，通过 fluent interface （流利的接口？我还没有找到合适的词汇，by Jason Qi）

  • 直接地，通过实例化类

Zend_Translate 的已注册的实例是这个助手的首选用法。你也可以简单地在添加适配器到注册表之前选择被使用的地点（locale）

Note: 我们用地点（locales）而不用语言是因为一种语音也可以包含一个地区。例如英语有不同的方言，有英国英语和美国英语，因此我们用“地点”而不说“语言”。

Example #19 已注册的实例

为使用已注册的实例就是创建一个 Zend_Translate 或者 Zend_Translate_Adapter 的实例并在 Zend_Registry 里用 Zend_Translate 作为它的键。

<?php
// 我们的例子适配器
$adapter = new Zend_Translate('array', array('simple' => 'einfach'), 'de');
Zend_Registry::set('Zend_Translate', $adapter);

// 在视图中
echo $this->translate('simple');
// 返回 'einfach'
?>

如果你熟悉 fluent interface ，那么也可以在视图里创建一个实例然后实例化这个助手。

Example #20 在视图里

为了使用 fluent interface ，创建一个 Zend_Translate 或者 Zend_Translate_Adapter 的实例，调用不带参数的助手并调用 setTranslator 方法。

<?php
// 在视图里
$adapter = new Zend_Translate('array', array('simple' => 'einfach'), 'de');
$this->translate()->setTranslator($adapter)->translate('simple');
// 返回 'einfach'
?>

如果你使用没有Zend_View的助手，那么你也可以直接使用它。

Example #21 直接用法

<?php
// 我们的例子适配器
$adapter = new Zend_Translate('array', array('simple' => 'einfach'), 'de');

// 实例化适配器
$translate = new Zend_View_Helper_Translate($adapter);
print $translate->translate('simple'); // this returns 'einfach'
?>

如果你不用 Zend_View 你将需要这样做并需要创建一个已翻译的输出。

就象已经知道，translate() 方法用来返回翻译。用需要的翻译适配器的信息 id 来调用它。但它也可以在翻译字符串里替换参数。因此，它有两个方法接受变量参数。或者是参数类表，或者是参数数组。如下例：

Example #22 单个参数

使用单个参数就把它添加到这个方法。

<?php
// 在视图里
$date = "Monday";
$this->translate("Today is %1\$s", $date);
// 应当返回 'Heute ist Monday'
?>

Note: 记住如果使用的参数也是文本，你可能也要翻译这些参数。

Example #23 参数列表

使用参数列表并添加给方法。

<?php
// 在视图里
$date = "Monday";
$month = "April";
$time = "11:20:55";
$this->translate("Today is %1\$s in %2\$s. Actual time: %3\$s", $date, $month, $time);
// 应当返回 'Heute ist Monday in April. Aktuelle Zeit: 11:20:55'
?>

Example #24 参数数组

使用参数数组并添加到方法。

<?php
// 在视图里
$date = array("Monday", "April", "11:20:55");
$this->translate("Today is %1\$s in %2\$s. Actual time: %3\$s", $date);
// 应当返回 'Heute ist Monday in April. Aktuelle Zeit: 11:20:55'
?>

有时候必需要修改翻译的地点。可以通过动态翻译或者把所有的静态翻译来完成。并且你可以使用参数类表和参数数组。在这两种情况下，地点被当作最后一个单个参数给出。

Example #25 动态修改地点 （locale）

<?php
// 在视图里
$date = array("Monday", "April", "11:20:55");
$this->translate("Today is %1\$s in %2\$s. Actual time: %3\$s", $date, 'it');
?>

这个例子为 messageid 返回意大利语的翻译。但它将只能用一次。下个翻译将从适配器里设置地点。通常地在添加它到注册表之前你将在翻译适配器里设置期望的地点。但你也可以从助手里设置地点：

Example #26 静态修改地点 （locale）

<?php
// 在视图里
$date = array("Monday", "April", "11:20:55");
$this->translate()->setLocale('it');
$this->translate("Today is %1\$s in %2\$s. Actual time: %3\$s", $date);
?>

在上面的例子里设置 'it' 为新的缺省地点，它将被用来给所有将来的翻译。

当然，还有 getLocale() 方法来获得当前设置的地点。

Example #27 获得当前设置的地点

<?php
// 在视图里
$date = array("Monday", "April", "11:20:55");

// 从上面的例子里返回 'de' 作为缺省地点
$this->translate()->getLocale();

$this->translate()->setLocale('it');
$this->translate("Today is %1\$s in %2\$s. Actual time: %3\$s", $date);

// 返回 'it' 为新的缺省地点
$this->translate()->getLocale();
?>

助手的路径

就像可以指定视图脚本的路径，控制器也可以为Zend_View设定助手类的路径。默认地，Zend_View会到 “Zend/View/Helper/”下查找助手类。可以用 setHelperPath() 和 addHelperPath() 方法来告诉 Zend_View 从其它地方来找路径。另外，你也可以指定类名的前缀，用于指定助手类所在的路径，允许给助手类命名空间。默认情况下，如果没有给出前缀，会假设使用“Zend_View_Helper_”。

<?php
$view = new Zend_View();

// 设置路径为：/path/to/more/helpers, 通过使用前缀 'My_View_Helper'
$view->setHelperPath('/path/to/more/helpers', 'My_View_Helper');

你可以用addHelperPath()来增加helper的路径， Zend_View将使用最近增加的路径。这样你可以使用自己的helper。

<?php
$view = new Zend_View();
// Add /path/to/some/helpers with class prefix 'My_View_Helper'
$view->addHelperPath('/path/to/some/helpers', 'My_View_Helper');
// Add /other/path/to/helpers with class prefix 'Your_View_Helper'
$view->addHelperPath('/other/path/to/helpers', 'Your_View_Helper');

// now when you call $this->helperName(), Zend_View will look first for
// "/path/to/some/helpers/HelperName" using class name "Your_View_Helper_HelperName",
// then for "/other/path/to/helpers/HelperName.php" using class name "My_View_Helper_HelperName",
// and finally for "Zend/View/Helper/HelperName.php" using class name "Zend_View_Helper_HelperName".

编写自定义的助手类

编写自定义的助手类很容易，只要遵循以下几个原则即可：

  • helper的类名最后部分必须是helper的名称，并使用混合大小写字格式。例如，你在写一个名为“specialPurpose”的类，类名将至少是"SpecialPurpose"，另外你还应该给类名加上前缀，建议将“View_Helper”作为前缀的一部份：“My_View_Helper_SpecialPurpose”。（注意大小写）你将需要将前缀（包含或不包含下划线）传递给addHelperPath() 或 setHelperPath()。

  • 类中必须有一个public的方法，该方法名与helper类名相同。该方法将在你的模板调用"$this->specialPurpose()"时执行。在我们的“specialPurpose”例子中，相应的方法声明可以是“public function specialPurpose()”。

  • 一般来说，助手类不应该echo或print或有其它形式的输出。它只需要返回值就可以了。返回的数据应当被转义。

  • 类文件的命名应该是助手类的名称，比如在"specialPurpose"例子中，文件要存为“SpecialPurpose.php”。

把助手类的文件放在你的助手路径下， Zend_View就会自动加载，实例化，持久化，并执行。

下面是一个SpecialPurpose 助手代码的例子：

<?php
class My_View_Helper_SpecialPurpose
{
    protected $_count = 0;
    public function specialPurpose()
    {
        $this->_count++;
        $output = "I have seen 'The Jerk' {$this->_count} time(s).";
        return htmlspecialchars($output);
    }
}

在视图代码中，可以调用 SpecialPurpose 助手任意次。它将被实例化一次，并且会在Zend_View实例的生命周期内持久存在。

<?php
// remember, in a view script, $this refers to the Zend_View instance.
echo $this->specialPurpose();
echo $this->specialPurpose();
echo $this->specialPurpose();

输出结果如下所示：

I have seen 'The Jerk' 1 time(s).
I have seen 'The Jerk' 2 time(s).
I have seen 'The Jerk' 3 time(s).

有时候需要访问调用Zend_View 对象－例如，如果需要使用已指定的编码字符集，或想解析其它视图脚本作为助手的一部分。为了访问视图对象，助手类应该有一个 setView($view) 方法，如下：

<?php
class My_View_Helper_ScriptPath
{
    public $view;

    public function setView(Zend_View_Interface $view)
    {
        $this->view = $view;
    }

    public function scriptPath($script)
    {
        return $this->view->getScriptPath($script);
    }
}

如果助手类有一个 setView() 方法，它将在助手类第一次实例化时被调用，并接受当前视图对象作为参数。是否让它在类里持久和如何访问，都完全取决于你。

视图脚本
Zend_View
Zend Framework手册 中文版
Zend_View_Abstract
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_View
  • 简介
  • 控制器脚本
  • 视图脚本
  • 视图助手（View Helper）
  • Zend_View_Abstract


视图脚本 - Zend Framework Manual

控制器脚本
Zend_View
Zend Framework手册 中文版
视图助手（View Helper）

视图脚本

Controller完成变量赋值和调用render()之后，Zend_View就会调用视图脚本并在Zend_View的实例内部执行。因此，在你的视图脚本内，$this指向Zend_View的实例。

从控制器传递到视图的变量以Zend_View实例属性的形式来调用。例如，控制器有一个变量"something" ，那么视图代码中就要用$this->something来调用。这样的作法可以让你分清哪些是来自Zend_View实例的变量，哪些是视图自身的变量。

为了说明，这里有一个例子：

<?php if ($this->books): ?>

    <!-- A table of some books. -->
    <table>
        <tr>
            <th>Author</th>
            <th>Title</th>
        </tr>

        <?php foreach ($this->books as $key => $val): ?>
        <tr>
            <td><?php echo $this->escape($val['author']) ?></td>
            <td><?php echo $this->escape($val['title']) ?></td>
        </tr>
        <?php endforeach; ?>

    </table>

<?php else: ?>

    <p>There are no books to display.</p>

<?php endif;

转义输出（Escaping Output）

View脚本的最重要的工作之一是保证输出的内容是合适的，比如需要避免跨站攻击漏洞(XSS)。除非你已经使用一个函数、类方法或助手类（helper）来转义内容，你需要在输出时对变量进行转义。

Zend_View带有一个escape()方法来提供这个功能：

<?php
// 不好的做法：
echo $this->variable;

// 好的做法：
echo $this->escape($this->variable);

默认地，escape()方法使用PHP函数htmlspecialchars()来过滤，但你也可以通过setEscape()方法来在Controller内告诉Zend_View需要怎么过滤。

<?php
//创建一个Zend_View实例
$view = new Zend_View();

//设定要使用的转义回调函数(callback)
$view->setEscape('htmlentities');

//或者使用一个静态类方法作为回调函数
$view->setEscape(array('SomeClass', 'methodName'));

//或者是一个对象实例的类方法
$obj = new SomeClass();
$view->setEscape(array($obj, 'methodName'));

//最后输出你的视图
echo $view->render(...);

设定的转义函数会将需要转义的变量作为其第一个参数，其它参数是可选的。

使用模板系统

尽管许多开发者觉得PHP本身就是一个强大的模板系统，但对模板设计师来说，使用PHP标签过于复杂。Zend_View提供了两套机制来同时满足这两种要求，一种是直接通过通过视图脚本，另一种是实现Zend_View_Interface接口。

使用View脚本的模板系统

View脚本可能要被用来初始化和操作一个其它模板对象的实例，例如PHPLIB风格的模板。这时View脚本可能是这样的：

<?php
include_once 'template.inc';
$tpl = new Template();

if ($this->books) {
    $tpl->setFile(array(
        "booklist" => "booklist.tpl",
        "eachbook" => "eachbook.tpl",
    ));

    foreach ($this->books as $key => $val) {
        $tpl->set_var('author', $this->escape($val['author']);
        $tpl->set_var('title', $this->escape($val['title']);
        $tpl->parse("books", "eachbook", true);
    }

    $tpl->pparse("output", "booklist");
} else {
    $tpl->setFile("nobooks", "nobooks.tpl")
    $tpl->pparse("output", "nobooks");
}

下面是相关的模板文件：

<!-- booklist.tpl -->
<table>
    <tr>
        <th>Author</th>
        <th>Title</th>
    </tr>
    {books}
</table>

<!-- eachbook.tpl -->
    <tr>
        <td>{author}</td>
        <td>{title}</td>
    </tr>

<!-- nobooks.tpl -->
<p>There are no books to display.</p>>

通过Zend_View_Interface接口使用模板系统

实现一个与Zend_View兼容的模板系统是很简单的。你只需要实现Zend_View_Interface接口即可，该接口定义了要实现兼容的最低要求。

/**
 * Return the actual template engine object
 * 返回实际模板系统的对象
 */
public function getEngine();

/**
 * Set the path to view scripts/templates
 * 设置视图脚本/模板的路径
 */
public function setScriptPath($path);

/**
 * Set a base path to all view resources
 * 给所有视图资源设置基本路径
 */
public function setBasePath($path, $prefix = 'Zend_View');

/**
 * Add an additional base path to view resources
 * 给视图资源添加另外的基本路径
 */
public function addBasePath($path, $prefix = 'Zend_View');

/**
 * Retrieve the current script paths
 * 获取当前脚本路径
 */
public function getScriptPaths();

/**
 * Overloading methods for assigning template variables as object properties
 * 重载方法，用于将赋值给模板变量，以对象属性的形式
 */
public function __set($key, $value);
public function __get($key);
public function __isset($key);
public function __unset($key);

/**
 * Manual assignment of template variables, or ability to assign multiple
 * variables en masse.
 * 手动设置模板变量，或者一次赋值多个变量的功能
 */
public function assign($spec, $value = null);

/**
 * Unset all assigned template variables
 * 消除所有已赋值的变量
 */
public function clearVars();

/**
 * Render the template named $name
 * 输出参数$name指定的某个模板
 */
public function render($name);

使用这个接口，把第三方的模板系统封装成Zend_View兼容的类是相当容易的。例如，下面是封装Smarty的示例代码：

require_once 'Zend/View/Interface.php';
require_once 'Smarty.class.php';

class Zend_View_Smarty implements Zend_View_Interface
{
    /**
     * Smarty object
     * @var Smarty
     */
    protected $_smarty;

    /**
     * Constructor
     *
     * @param string $tmplPath
     * @param array $extraParams
     * @return void
     */
    public function __construct($tmplPath = null, $extraParams = array())
    {
        $this->_smarty = new Smarty;

        if (null !== $tmplPath) {
            $this->setScriptPath($tmplPath);
        }

        foreach ($extraParams as $key => $value) {
            $this->_smarty->$key = $value;
        }
    }

    /**
     * Return the template engine object
     *
     * @return Smarty
     */
    public function getEngine()
    {
        return $this->_smarty;
    }

    /**
     * Set the path to the templates
     *
     * @param string $path The directory to set as the path.
     * @return void
     */
    public function setScriptPath($path)
    {
        if (is_readable($path)) {
            $this->_smarty->template_dir = $path;
            return;
        }

        throw new Exception('Invalid path provided');
    }

    /**
     * Retrieve the current template directory
     *
     * @return string
     */
    public function getScriptPaths()
    {
        return array($this->_smarty->template_dir);
    }

    /**
     * Alias for setScriptPath
     *
     * @param string $path
     * @param string $prefix Unused
     * @return void
     */
    public function setBasePath($path, $prefix = 'Zend_View')
    {
        return $this->setScriptPath($path);
    }

    /**
     * Alias for setScriptPath
     *
     * @param string $path
     * @param string $prefix Unused
     * @return void
     */
    public function addBasePath($path, $prefix = 'Zend_View')
    {
        return $this->setScriptPath($path);
    }

    /**
     * Assign a variable to the template
     *
     * @param string $key The variable name.
     * @param mixed $val The variable value.
     * @return void
     */
    public function __set($key, $val)
    {
        $this->_smarty->assign($key, $val);
    }

    /**
     * Retrieve an assigned variable
     *
     * @param string $key The variable name.
     * @return mixed The variable value.
     */
    public function __get($key)
    {
        return $this->_smarty->get_template_vars($key);
    }

    /**
     * Allows testing with empty() and isset() to work
     *
     * @param string $key
     * @return boolean
     */
    public function __isset($key)
    {
         return (null !== $this->_smarty->get_template_vars($key));
    }

    /**
     * Allows unset() on object properties to work
     *
     * @param string $key
     * @return void
     */
    public function __unset($key)
    {
        $this->_smarty->clear_assign($key);
    }

    /**
     * Assign variables to the template
     *
     * Allows setting a specific key to the specified value, OR passing an array
     * of key => value pairs to set en masse.
     *
     * @see __set()
     * @param string|array $spec The assignment strategy to use (key or array of key
     * => value pairs)
     * @param mixed $value (Optional) If assigning a named variable, use this
     * as the value.
     * @return void
     */
    public function assign($spec, $value = null)
    {
        if (is_array($spec)) {
            $this->_smarty->assign($spec);
            return;
        }

        $this->_smarty->assign($spec, $value);
    }

    /**
     * Clear all assigned variables
     *
     * Clears all variables assigned to Zend_View either via {@link assign()} or
     * property overloading ({@link __get()}/{@link __set()}).
     *
     * @return void
     */
    public function clearVars()
    {
        $this->_smarty->clear_all_assign();
    }

    /**
     * Processes a template and returns the output.
     *
     * @param string $name The template to process.
     * @return string The output.
     */
    public function render($name)
    {
        return $this->_smarty->fetch($name);
    }
}

在这个示例中，实例化Zend_View_Smarty而不是Zend_View，然后就像使用 Zend_View一样地使用它。

$view = new Zend_View_Smarty();
$view->setScriptPath('/path/to/templates');
$view->book = 'Zend PHP 5 Certification Study Guide';
$view->author = 'Davey Shafik and Ben Ramsey'
$rendered = $view->render('bookinfo.tpl');
控制器脚本
Zend_View
Zend Framework手册 中文版
视图助手（View Helper）
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_View
  • 简介
  • 控制器脚本
  • 视图脚本
  • 视图助手（View Helper）
  • Zend_View_Abstract


Zend_View_Abstract - Zend Framework Manual

视图助手（View Helper）
Zend_View
Zend Framework手册 中文版
Zend_Wildfire

Zend_View_Abstract

Zend_View_Abstract 是个基础类，Zend_View 就是继承它的并声明 _run() 方法的具体实现 （由 render() 调用 ）。

很多开发者发现他们想继承 Zend_View_Abstract 并添加自定义的函数，不可避免地碰到它的包括许多私有成员的设计问题。本文档解释其中缘由。

Zend_View 有点反模板引擎，它使用 PHP 本身作为模板，结果所有的 PHP 可用并且视图脚本继承了它所调用对象的范围 （scope）。

It is this latter point that is salient to the design decisions. 在内部，Zend_View::_run() 做：

<?php
protected function _run()
{
    include func_get_arg(0);
}
?>

这样，视图脚本拥有访问当前对象 ($this) 和任何那个对象的方法和成员 的权限，因为许多操作基于有限可见性的成员，这会引起问题：视图脚本可以直接调用方法或修改至关重要的属性。想象一下脚本意外地重写 $_path 或 $_file －任何进一步地调用 render() 或视图助手将会中断。

幸好，PHP 5 对这个可见性声明有个方案：私有成员（private member）不能由继承该类的对象访问。所以我们就这样设计：因为 Zend_View 继承 Zend_View_Abstract，视图脚本就这样限制到只有 Zend_View_Abstract 的 protected 或 public 成员和方法。这样有效地限制了它可以执行的动作，保证了关键的安全区域不被视图脚本修改。

视图助手（View Helper）
Zend_View
Zend Framework手册 中文版
Zend_Wildfire
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_View
  • 简介
  • 控制器脚本
  • 视图脚本
  • 视图助手（View Helper）
  • Zend_View_Abstract


Zend_Wildfire - Zend Framework Manual

Zend_View_Abstract
Zend Framework Reference
Zend Framework手册 中文版
Zend_Wildfire

Zend_Wildfire

Table of Contents
  • Zend_Wildfire
Zend_View_Abstract
Zend Framework Reference
Zend Framework手册 中文版
Zend_Wildfire
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


Zend_Wildfire - Zend Framework Manual

Zend_Wildfire
Zend_Wildfire
Zend Framework手册 中文版
Zend_XmlRpc

Zend_Wildfire

Zend_Wildfire is a component that facilitates communication between PHP code and » Wildfire client components.

The purpose of the Wildfire Project is to develop standardized communication channels between a large variety of components and a dynamic and scriptable plugin architecture. At this time, the primary focus is to provide a system that allows server-side PHP code to inject logging messages into the » Firebug Console.

The Zend_Log_Writer_Firebug component is provided for the purpose of logging to Firebug, and a communication protocol has been developed that uses HTTP request and response headers to send data between the server and client components. It is great for logging intelligence data to the browser that is generated during script execution, without interfering with the page content. With this approach, it is possible to debug AJAX requests that require clean JSON and XML responses.

There is also a Zend_Db_Profiler_Firebug component to log database profiling information to Firebug.

Zend_Wildfire
Zend_Wildfire
Zend Framework手册 中文版
Zend_XmlRpc
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Wildfire
  • Zend_Wildfire


Zend_XmlRpc - Zend Framework Manual

Zend_Wildfire
Zend Framework Reference
Zend Framework手册 中文版
Introduction

Zend_XmlRpc

Table of Contents
  • Introduction
  • Zend_XmlRpc_Client
  • Zend_XmlRpc_Server
Zend_Wildfire
Zend Framework Reference
Zend Framework手册 中文版
Introduction
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


Introduction - Zend Framework Manual

Zend_XmlRpc
Zend_XmlRpc
Zend Framework手册 中文版
Zend_XmlRpc_Client

Introduction

From its » home page, XML-RPC is described as a "...remote procedure calling using HTTP as the transport and XML as the encoding. XML-RPC is designed to be as simple as possible, while allowing complex data structures to be transmitted, processed and returned."

Zend Framework provides support for both consuming remote XML-RPC services and building new XML-RPC servers.

Zend_XmlRpc
Zend_XmlRpc
Zend Framework手册 中文版
Zend_XmlRpc_Client
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_XmlRpc
  • Introduction
  • Zend_XmlRpc_Client
  • Zend_XmlRpc_Server


Zend_XmlRpc_Client - Zend Framework Manual

Introduction
Zend_XmlRpc
Zend Framework手册 中文版
Zend_XmlRpc_Server

Zend_XmlRpc_Client

介绍

Zend Framework 通过 Zend_XmlRpc_Client 作为客户端提供了调用远程 XML-RPC 服务的功能。主要功能包括在 PHP 和 XML-RPC 之间进行类型的自动转换， 服务代理对象（a server proxy object），和访问服务器的自省功能 （introspection capabilities）。

方法调用

Zend_XmlRpc_Client 的构造函数接受 XML-RPC 服务器端 URL 地址作为第一个参数。返回新的实例可以用来调用这个服务器端任意数量的远程方法。

使用 XML-RPC 客户端调用远程方法，需要实例化它并且使用 call() 实力方法。下面的代码演示了调用 Zend Framework 网站上的 XML-RPC 服务。 你可以使用它测试和学习 Zend_XmlRpc 组件。

Example #1 XML-RPC 方法调用

require_once 'Zend/XmlRpc/Client.php';

$client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');

echo $client->call('test.sayHello');

// hello

从远程调用返回的 XML-RPC 值将会自动编排和转换为等价的 PHP 原始类型。 在上面的例子中，一个 PHP string 会返回并即刻可以使用。

call() 方法接受远程调用的名字作为第一个参数。如果远程调用需要其他参数， 可以通过 call() 的第二个可选参数使用 array 的形式传递到远程方法。

Example #2 XML-RPC 带参数的方法调用

require_once 'Zend/XmlRpc/Client.php';

$client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');

$arg1 = 1.1;
$arg2 = 'foo';

$result = $client->call('test.sayHello', array($arg1, $arg2));

// $result is a native PHP type

如果远程方法不需要任何参数，这个可选参数可以留空或者传递一个空的 array() 过去。远程方法的参数数组可以包含原始的 PHP 类型，Zend_XmlRpc_Value 对象，或者两种的混合。

call() 方法会自动转换 XML-PRC 响应并返回等价的 PHP 原始类型。 返回值的 Zend_XmlRpc_Response 对象也可以在调用之后使用 getLastResponse() 方法获得。

类型及转换

一些远程方法调用时需要参数。它们作为数组传递到 Zend_XmlRpc_Client 的 call() 方法的第二个参数。每个参数，不论是原始的 PHP 类型， 还是一个对象表示的特定的 XML-RPC 类型（一个 Zend_XmlRpc_Value 对象）都会自动转换。

PHP 原始类型作为参数

原始 PHP 变量如 string，integer， float，boolean，array 或者 object 都可以作为参数传递到 call()。 在这种情况下，每个 PHP 原始类型将会自动检测和转换到一个 XML-RPC 类型， 如下表所示：

PHP 与 XML-RPC 的类型转换
PHP 原始类型 | XML-RPC 类型
integer | int
double | double
boolean | boolean
string | string
array | array
associative array | struct
object | array

Note: 一个空的数组会如何转换？
 传递空数组到 XML-RPC 方法，由于它既可表示为一个数组也可表示为一个结构， 所以会产生问题。Zend_XmlRpc_Client 会监测这种情况并向服务器进行一个 system.methodSignature 请求来决定实际将要转换到的 XML-RPC 类型。
不过，这样做本身就可能导致问题出现。首先，服务器不支持 system.methodSignature 将会产生一个失败请求，同时 Zend_XmlRpc_Client 会强制转换这个值为 XML-RPC 数组类型。此外，这意味着任何数组参数都可能导致对远端服务器的一次额外请求。
可以在 XML-RPC 调用前调用 setSkipSystemLookup() 方法，以便完全屏蔽这个查询：

$client->setSkipSystemLookup(true);
$result = $client->call('foo.bar', array(array()));

Zend_XmlRpc_Value 对象作为参数

也可以创建 Zend_XmlRpc_Value 实例作为参数，以表示特定的 XML-RPC 类型。这样做的主要原因如下：

  • 当希望确定的参数类型被传递传递时（例如，方法需要一个整型， 而可能从数据库获得的是一个字符串）。

  • 当方法需要 base64 或者 dateTime.iso8601 类型时（这些在 PHP 原始类型中不存在）。

  • 当自动转换失败时（例如，你希望传递一个空的 XML-RPC 结构作为参数。空的结构在 PHP 中应当是一个空的数组， 但是如果传递一个空数组作为参数，它将被自动转换为 XML-RPC 数组，虽然它同数组没有联系）。

有两种方法创建 Zend_XmlRpc_Value 对象：直接实例化某个 Zend_XmlRpc_Value 的子类；或者使用静态工厂方法 Zend_XmlRpc_Value::getXmlRpcValue()。

Zend_XmlRpc_Value 对象作为 XML-RPC 类型
XML-RPC 类型 | Zend_XmlRpc_Value 常量 | Zend_XmlRpc_Value 对象
int | Zend_XmlRpc_Value::XMLRPC_TYPE_INTEGER | Zend_XmlRpc_Value_Integer
double | Zend_XmlRpc_Value::XMLRPC_TYPE_DOUBLE | Zend_XmlRpc_Value_Double
boolean | Zend_XmlRpc_Value::XMLRPC_TYPE_BOOLEAN | Zend_XmlRpc_Value_Boolean
string | Zend_XmlRpc_Value::XMLRPC_TYPE_STRING | Zend_XmlRpc_Value_String
base64 | Zend_XmlRpc_Value::XMLRPC_TYPE_BASE64 | Zend_XmlRpc_Value_Base64
dateTime.iso8601 | Zend_XmlRpc_Value::XMLRPC_TYPE_DATETIME | Zend_XmlRpc_Value_DateTime
array | Zend_XmlRpc_Value::XMLRPC_TYPE_ARRAY | Zend_XmlRpc_Value_Array
struct | Zend_XmlRpc_Value::XMLRPC_TYPE_STRUCT | Zend_XmlRpc_Value_Struct

Note: 自动转换
 当创建新的 Zend_XmlRpc_Value 对象时，它的值通过 PHP 类型设置。PHP 类型将会通过 PHP 类型转换到指定的类型。例如， 如果给 Zend_XmlRpc_Value_Integer 对象提供一个字符串，它将由 (int)$value 转换。

服务代理对象

另一个使用 XML-RPC 客户端调用远程方法的途径是使用服务代理。这是一个 PHP 对象代理远程 XML-RPC 名字空间，使其工作方式尽可能的贴近原始的 PHP 对象。

调用 Zend_XmlRpc_Client 实例的 getProxy() 方法实例化一个服务器代理。该方法将返回一个 Zend_XmlRpc_Client_ServerProxy 实例。对服务器代理方法的任何调用将会传递到远程，而参数的传递就如同其他任何 PHP 方法一样。

Example #3 代理默认命名空间

require_once 'Zend/XmlRpc/Client.php';

$client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');

$server = $client->getProxy();           // Proxy the default namespace

$hello = $server->test->sayHello(1, 2);  // test.Hello(1, 2) returns "hello"

getProxy() 方法接受一个可选参数作为将要代理的远端服务器的命名空间。 如果没有指定这个命名空间，默认的命名空间会被代理。在下面的例子中，命名空间 test 将会被代理。

Example #4 代理任意命名空间

$client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');

$test  = $client->getProxy('test');     // Proxy the "test" namespace

$hello = $test->sayHello(1, 2);         // test.Hello(1,2) returns "hello"

若远端服务器支持任意深度嵌套的命名空间，仍然可以通过服务器代理使用。例如， 如果上面的例子有一个方法 test.foo.bar()，则可以使用 $test->foo->bar() 来调用。

错误处理

在 XML-RPC 方法中可能出现两种错误：HTTP 错误和 XML-RPC 失败。 Zend_XmlRpc_Client 可以识别并分别检测并捕获它们。

HTTP 错误

当 HTTP 错误发生时，例如远端 HTTP 服务器返回 404 Not Found，将会抛出一个 Zend_XmlRpc_Client_HttpException 异常。

Example #5 处理 HTTP 错误

$client = new Zend_XmlRpc_Client('http://foo/404');

try {

    $client->call('bar', array($arg1, $arg2));

} catch (Zend_XmlRpc_Client_HttpException $e) {

    // $e->getCode() returns 404
    // $e->getMessage() returns "Not Found"

}

不论是如何使用 XML-RPC 客户端的，当 HTTP 错误发生时，都会抛出 Zend_XmlRpc_Client_HttpException 异常。

XML-RPC 失败

XML-RPC 失败类似于 PHP 异常。它是从 XML-RPC 方法调用返回的，有着指定的类型， 同时具有错误代码和错误消息。XML-RPC 失败的处理方式随着 Zend_XmlRpc_Client 使用方式不同而不同。

当 call() 方法或者服务器代理对象被使用时，XML-RPC 失败会抛出一个 Zend_XmlRpc_Client_FaultException 异常。异常代码和消息会直接映射到原始的 XML-RPC 失败相应的内容上去。

Example #6 处理 XML-RPC 失败

$client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');

try {

    $client->call('badMethod');

} catch (Zend_XmlRpc_Client_FaultException $e) {

    // $e->getCode() returns 1
    // $e->getMessage() returns "Unknown method"

}

当请求时使用 call() 方法，会在失败的时候抛出 Zend_XmlRpc_Client_FaultException 异常。可以调用 getLastResponse() 获得包含在 Zend_XmlRpc_Response 对象中的异常。

当请求时使用 doRequest() 方法，则不会抛出异常。将返回一个包含错误信息的 Zend_XmlRpc_Response 对象。可以使用 Zend_XmlRpc_Response 示例的 isFault() 方法检查。

服务器自省（introspection）

一些 XML-RPC 服务器支持 system. 命名空间下的自省。Zend_XmlRpc_Client 对这些服务器的这种功能特别进行了支持。

调用 Zend_XmlRpcClient 的 getIntrospector() 方法可以获得 Zend_XmlRpc_Client_ServerIntrospection 实例。 通过它可以使用服务器的自省功能。

从请求作出回应

本质上说，Zend_XmlRpc_Client 实例的 call() 方法创建了请求对象（Zend_XmlRpc_Request）并将其传递给另一个方法 doRequest()，doRequest() 方法返回响应对象（Zend_XmlRpc_Response）。

doRequest() 方法也可直接调用。

Example #7 处理请求作出回应

$client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');

$request = new Zend_XmlRpc_Request();
$request->setMethod('test.sayHello');
$request->setParams(array('foo', 'bar'));

$client->doRequest($request);

// $server->getLastRequest() returns instanceof Zend_XmlRpc_Request
// $server->getLastResponse() returns instanceof Zend_XmlRpc_Response

无论客户端通过任何方法调用 XML-RPC 方法，如 call() 方法、
doRequest() 方法或者服务器代理，最后一个请求对象以及对应的响应对象总是可以分别调用
getLastRequest() 和 getLastResponse() 获得。

HTTP 客户端和测试

在前面所有的例子中，从未指定 HTTP 客户端。这是因为在使用 Zend_XmlRpc_Client 时会使用默认配置自动创建一个 Zend_Http_Client 实例。

可以在任何时候使用 getHttpClient() 方法获得 HTTP 客户端。 多数情况下默认的 HTTP 客户端已经足够使用。不过仍然可以使用 setHttpClient() 方法设置新的 HTTP 客户端实例。

setHttpClient() 在单元测试时特别有用。在 Zend_Http_Client_Adapter_Test 中测试时可以欺骗远程服务器。阅读 Zend_XmlRpc_Client 的单元测试了解如何这样做。

Introduction
Zend_XmlRpc
Zend Framework手册 中文版
Zend_XmlRpc_Server
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_XmlRpc
  • Introduction
  • Zend_XmlRpc_Client
  • Zend_XmlRpc_Server


Zend_XmlRpc_Server - Zend Framework Manual

Zend_XmlRpc_Client
Zend_XmlRpc
Zend Framework手册 中文版
ZendX_Console_Process_Unix

Zend_XmlRpc_Server

介绍

Zend_XmlRpc_Server 依照 » www.xmlrpc.com 上的规格描述 实现了一个全功能 XML-RPC 服务器。同时，它还实现了允许批量传输（boxcarring）的 system.multicall() 方法。

基本使用

最基本的使用实例：

<?php
require_once 'Zend/XmlRpc/Server.php';
require_once 'My/Service/Class.php';

$server = new Zend_XmlRpc_Server();
$server->setClass('My_Service_Class');
echo $server->handle();

服务器结构

Zend_XmlRpc_Server 是由各种不同组件组成，包括服务器自身用于接收请求或进行相应的组件， 以及错误对象。

为了启动 Zend_XmlRpc_Server，开发人员必须通过 setClass() 和 addFunction() 方法附加一个或者多个类或函数到服务器。

完成附加操作后，则可以向 Zend_XmlRpc_Server::handle() 传递 Zend_XmlRpc_Request 对象，如果没有提供它将实例化一个 Zend_XmlRpc_Request_Http 对象用于从 php://input 获取请求。

这时 Zend_XmlRpc_Server::handle() 将基于请求尝试调度合适的处理程序。 它将返回基于 Zend_XmlRpc_Response 的对象或者 Zend_XmlRpc_Server_Fault 对象。这些对象都有 __toString() 用来创建合法的，允许直接返回的 XML-RPC 的 XML 响应文本。

转换

Zend_XmlRpc_Server 允许开发人员附加函数和类方法作为 XML-RPC 方法来调度。通过 Zend_Server_Reflection 自省所有附加的方法，使用函数和方法的文档部分(docblocks) 决定方法的帮助文档和方法标识。

XML-RPC 类型不可能与 PHP 类型一一对应。然而程序仍然利用 @param 和 @return 的值列表尽可能的猜测最合适的类型。一些 XML-RPC 类型没有合适的 PHP 中的匹配， 所以应当在 phpdoc 中对 XML-RPC 类型给予提示。这些包括：

  • dateTime.iso8601，字符串格式 YYYYMMDDTHH:mm:ss

  • base64, base64 编码数据

  • struct, 结构匹配的数组

下面的例子演示了如何增加这样的提示：

<?php
/**
* 这是一个演示函数
*
* @param base64 $val1 Base64-encoded data
* @param dateTime.iso8601 $val2 An ISO date
* @param struct $val3 An associative array
* @return struct
*/
function myFunc($val1, $val2, $val3)
{
}

PhpDocumentor 不会验证参数和返回值的类型，所以这对 API 文档没有任何影响。 而且当服务器验证调用方法所提供的参数时，就必须提供提示。

最有效的办法是未参数和返回值指定多个类型；XML-RPC 文档甚至建议 system.methodSignature 应当返回一个数组，含有所有可能的方法标识（例如，参数和返回值的所有可能的组合）。 你可以像通常那样在 PhpDocumentor 中使用“|”符号做到这点：

<?php
/**
* 这是一个演示函数
*
* @param string|base64 $val1 String or base64-encoded data
* @param string|dateTime.iso8601 $val2 String or an ISO date
* @param array|struct $val3 Normal indexed array or an associative array
* @return boolean|struct
*/
function myFunc($val1, $val2, $val3)
{
}

需要注意的是，允许多个标识可能干扰使用服务的开发人员；一般来说，一个 XML-RPC 方法只应该有一个标识。

使用命名空间

XML-RPC 有名字空间的概念；通常，它允许使用“.”分割 XML-RPC 方法到各个命名空间。 这有助于防止不同类提供的不同服务方法之间的命名冲突。例如，XML-RPC 服务在命名空间“system”中保留了一些方法：

  • system.listMethods

  • system.methodHelp

  • system.methodSignature

从内部来讲，这些方法映射到 Zend_XmlRpc_Server 的同名方法上。

如果想要为服务方法增加命名空间，只要在附加一个函数或类时，添加命名空间到适当的方法上：

<?php
// My_Service_Class 类的公共方法将被映射为 myservice.METHODNAME
$server->setClass('My_Service_Class', 'myservice');

// 函数“somefunc”将被映射为 funcs.somefunc
$server->addFunction('somefunc', 'funcs');

自定义请求对象

多数情况下，只需要使用 Zend_XmlRpc_Server 默认提供的请求类型 Zend_XmlRpc_Request_Http。然而，仍然有可能在 CLI、GUI 或者其他环境使用 XML-RPC，亦或需要记录每个请求。需要从 Zend_XmlRpc_Request 继承，创建自定义的对象来完成这个工作。最重要的是记得确保实现 getMethod() 和 getParams() 方法，这样 XML-RPC 服务器就可以获取必要的信息进行调度。

自定义响应对象

和请求对象一样，Zend_XmlRpc_Server 可以返回自定义响应对象；默认情况下， Zend_XmlRpc_Response_Http 对象被返回，这个对象包含一个合适的用于 XML-RPC 的 HTTP Content-Type 头。使用自定义对象的情况可能是需要记录响应，或需要发送响应到 STDOUT。

在调用 handle() 之前使用 Zend_XmlRpc_Server::setResponseClass() 指定自定义的响应类。

处理错误产生的异常

Zend_XmlRpc_Server 会捕获调度方法产生的一场，同时生成 XML-RPC 失败响应。 然而，默认情况下，异常消息和代码不出现在失败响应中。有意设计成如此形式主要是为了保护代码； 许多异常会暴露超出预期的大量关于代码和开发环境的信息（常见的例子如数据库抽象层或访问层一场）。

异常类也可以加入白名单中作为失败响应。要做到这点，只需使用 Zend_XmlRpc_Server_Fault::attachFaultException() 添加一个异常类到白名单即可：

<?php
Zend_XmlRpc_Server_Fault::attachFaultException('My_Project_Exception');

如果你使用的是一个继承于其他项目的异常，可以一次将整个类树加入白名单。 Zend_XmlRpc_Server_Exceptions 总是在白名单中，用于报告指定的内部错误（如未定义的方法等）。

一个未在白名单中指定的异常将会返回错误代码“404”，错误消息“Unknown error”（未知错误）。

在请求之间缓存服务器定义

附加多个类到 XML-RPC 服务器实例可能消耗大量的资源；每一个类必须使用反射 API 进行自省（通过 Zend_Server_Reflection），生成一个包含有所有可用方法的列表用于服务器调用。

为了减少这种性能污点，可以使用 Zend_XmlRpc_Server_Cache 来缓存请求之间的服务器定义。 联合 __autoload() 使用，可以极大的提高性能。

实例如下：

<?php
require_once 'Zend/Loader.php';
require_once 'Zend/XmlRpc/Server.php';
require_once 'Zend/XmlRpc/Server/Cache.php';

function __autoload($class)
{
    Zend_Loader::loadClass($class);
}

$cacheFile = dirname(__FILE__) . '/xmlrpc.cache';
$server = new Zend_XmlRpc_Server();

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';

    $server->setClass('My_Services_Glue', 'glue');   // glue. namespace
    $server->setClass('My_Services_Paste', 'paste'); // paste. namespace
    $server->setClass('My_Services_Tape', 'tape');   // tape. namespace

    Zend_XmlRpc_Server_Cache::save($cacheFile, $server);
}

echo $server->handle();

上面的例子尝试从当前脚本所在目录下的 xmlrpc.cache 文件获取服务器定义。 如果失败的话就加载需要的服务类，附加他们到服务器实例，并尝试使用服务器定义创建新的缓存文件。

使用实例

下面有一些有用的例子，向开发人员展示了可能用到的各种情况。 每一个实例都是建立在前一个实例基础上的扩充。

基本使用

下面的例子演示了附加一个函数作为 XML-RPC 的调度方法，并用其处理请求。

<?php
require_once 'Zend/XmlRpc/Server.php';

/**
 * 返回 MD5 值
 *
 * @param string $value Value to md5sum
 * @return string MD5 sum of value
 */
function md5Value($value)
{
    return md5($value);
}

$server = new Zend_XmlRpc_Server();
$server->addFunction('md5Value');
echo $server->handle();

附加一个类

下面的例子演示了附加一个类的公共方法作为 XML-RPC 的调度方法。

<?php
require_once 'Zend/XmlRpc/Server.php';
require_once 'Services/Comb.php';

$server = new Zend_XmlRpc_Server();
$server->setClass('Services_Comb');
echo $server->handle();

利用命名空间附加多个类

下面的例子演示了附加多个类，每个类都有自己的命名空间。

<?php
require_once 'Zend/XmlRpc/Server.php';
require_once 'Services/Comb.php';
require_once 'Services/Brush.php';
require_once 'Services/Pick.php';

$server = new Zend_XmlRpc_Server();
$server->setClass('Services_Comb', 'comb');   // methods called as comb.*
$server->setClass('Services_Brush', 'brush'); // methods called as brush.*
$server->setClass('Services_Pick', 'pick');   // methods called as pick.*
echo $server->handle();

指定异常作为合法的失败响应

下面的例子允许任何 Services_Exception 的派生类作为失败响应返回其代码和消息。

<?php
require_once 'Zend/XmlRpc/Server.php';
require_once 'Zend/XmlRpc/Server/Fault.php';
require_once 'Services/Exception.php';
require_once 'Services/Comb.php';
require_once 'Services/Brush.php';
require_once 'Services/Pick.php';

// 允许 Services_Exceptions 作为响应失败输出
Zend_XmlRpc_Server_Fault::attachFaultException('Services_Exception');

$server = new Zend_XmlRpc_Server();
$server->setClass('Services_Comb', 'comb');   // methods called as comb.*
$server->setClass('Services_Brush', 'brush'); // methods called as brush.*
$server->setClass('Services_Pick', 'pick');   // methods called as pick.*
echo $server->handle();

设置自定义请求对象

下面的例子演示了实例化自定义请求对象并将其传递到服务器进行处理。

<?php
require_once 'Zend/XmlRpc/Server.php';
require_once 'Zend/XmlRpc/Server/Fault.php';
require_once 'Services/Request.php';
require_once 'Services/Exception.php';
require_once 'Services/Comb.php';
require_once 'Services/Brush.php';
require_once 'Services/Pick.php';

// 允许 Services_Exceptions 作为响应失败输出
Zend_XmlRpc_Server_Fault::attachFaultException('Services_Exception');

$server = new Zend_XmlRpc_Server();
$server->setClass('Services_Comb', 'comb');   // methods called as comb.*
$server->setClass('Services_Brush', 'brush'); // methods called as brush.*
$server->setClass('Services_Pick', 'pick');   // methods called as pick.*

// 创建请求对象
$request = new Services_Request();

echo $server->handle($request);

设置自定义响应对象

下面的例子演示了指定自定义类作为响应返回。

<?php
require_once 'Zend/XmlRpc/Server.php';
require_once 'Zend/XmlRpc/Server/Fault.php';
require_once 'Services/Request.php';
require_once 'Services/Response.php';
require_once 'Services/Exception.php';
require_once 'Services/Comb.php';
require_once 'Services/Brush.php';
require_once 'Services/Pick.php';

// 允许 Services_Exceptions 作为响应失败输出
Zend_XmlRpc_Server_Fault::attachFaultException('Services_Exception');

$server = new Zend_XmlRpc_Server();
$server->setClass('Services_Comb', 'comb');   // methods called as comb.*
$server->setClass('Services_Brush', 'brush'); // methods called as brush.*
$server->setClass('Services_Pick', 'pick');   // methods called as pick.*

// 创建请求对象
$request = new Services_Request();

// 设置自定义响应
$server->setResponseClass('Services_Response');

echo $server->handle($request);

在请求之间缓存服务器定义

下面的例子演示了在请求之间缓存服务器定义。

<?php
require_once 'Zend/XmlRpc/Server.php';
require_once 'Zend/XmlRpc/Server/Fault.php';
require_once 'Zend/XmlRpc/Server/Cache.php';
require_once 'Services/Request.php';
require_once 'Services/Response.php';
require_once 'Services/Exception.php';
require_once 'Services/Comb.php';
require_once 'Services/Brush.php';
require_once 'Services/Pick.php';

// 指定一个缓存文件
$cacheFile = dirname(__FILE__) . '/xmlrpc.cache';

// 允许 Services_Exceptions 作为响应失败输出
Zend_XmlRpc_Server_Fault::attachFaultException('Services_Exception');

$server = new Zend_XmlRpc_Server();

// 尝试从缓存中获取服务器定义
if (!Zend_XmlRpc_Server_Cache::get($cacheFile, $server)) {
    $server->setClass('Services_Comb', 'comb');   // methods called as comb.*
    $server->setClass('Services_Brush', 'brush'); // methods called as brush.*
    $server->setClass('Services_Pick', 'pick');   // methods called as pick.*

    // 保存缓存
    Zend_XmlRpc_Server_Cache::save($cacheFile, $server));
}

// 创建请求对象
$request = new Services_Request();

// 设置自定义响应
$server->setResponseClass('Services_Response');

echo $server->handle($request);
Zend_XmlRpc_Client
Zend_XmlRpc
Zend Framework手册 中文版
ZendX_Console_Process_Unix
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_XmlRpc
  • Introduction
  • Zend_XmlRpc_Client
  • Zend_XmlRpc_Server


ZendX_Console_Process_Unix - Zend Framework Manual

Zend_XmlRpc_Server
Zend Framework Reference
Zend Framework手册 中文版
ZendX_Console_Process_Unix

ZendX_Console_Process_Unix

Table of Contents
  • ZendX_Console_Process_Unix
Zend_XmlRpc_Server
Zend Framework Reference
Zend Framework手册 中文版
ZendX_Console_Process_Unix
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


ZendX_Console_Process_Unix - Zend Framework Manual

ZendX_Console_Process_Unix
ZendX_Console_Process_Unix
Zend Framework手册 中文版
ZendX_JQuery

ZendX_Console_Process_Unix

Introduction

ZendX_Console_Process_Unix allows developers to spawn an object as a new process, and so do multiple tasks in parallel on console environments. Through its specific nature, it is only working on *nix based systems like Linux, Solaris, Mac/OSx and such. Additionally, the shmop_*, pcntl_* and posix_* modules are required for this component to run. If one of the requirements is not met, it will throw an exception after instantiating the component.

Basic usage of ZendX_Console_Process_Unix

ZendX_Console_Process_Unix is an abstract class, which requires the user to extend it. It has a single abstract method called _run() which has to be implemented to create a working process. It also comes with multiple methods for checking the alive status and share variables between the parent and the child process.

The _run() method and every method which is called by it is executed by the child process. Every other method which is called directly by the parent is executed by the parent process.

setVariable() and getVariable() can be used from both the parent- and the child process to share variables. To observe the alive status, the child process should call _setAlive() in a frequent interval, so that the parent process can check the last alive time via getLastAlive(). To get the PID of the child process, the parent can call getPid().

Example #1 Basic example for processing

This example illustrates a basic child process

  1. class MyProcess extends ZendX_Console_Process_Unix
  2. {
  3.     protected function _run()
  4.     {
  5.         for ($i = 0; $i < 10; $i++) {
  6.             // Doing something really important which can't wait: sleeping
  7.             sleep(1);
  8.         }
  9.     }
  10. }
  11.
  12. // This part should last about 10 seconds, not 20.
  13. $process1 = new MyProcess();
  14. $process1->start();
  15.
  16. $process2 = new MyProcess();
  17. $process2->start();
  18.
  19. while ($process1->isRunning() && $process2->isRunning()) {
  20.     sleep(1);
  21. }
  22.
  23. echo 'All processes completed';

In this example a process is forked twice and executed. As every process runs 10 seconds, the parent process will be finished after 10 seconds (and not 20).

ZendX_Console_Process_Unix
ZendX_Console_Process_Unix
Zend Framework手册 中文版
ZendX_JQuery
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • ZendX_Console_Process_Unix
  • ZendX_Console_Process_Unix


ZendX_JQuery - Zend Framework Manual

ZendX_Console_Process_Unix
Zend Framework Reference
Zend Framework手册 中文版
Introduction

ZendX_JQuery

Table of Contents
  • Introduction
  • ZendX_JQuery View Helpers
  • ZendX_JQuery Form Elements and Decorators
ZendX_Console_Process_Unix
Zend Framework Reference
Zend Framework手册 中文版
Introduction
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery


Introduction - Zend Framework Manual

ZendX_JQuery
ZendX_JQuery
Zend Framework手册 中文版
ZendX_JQuery View Helpers

Introduction

As of version 1.7, Zend Framework integrates » jQuery view and form helpers through its extras library. The jQuery support is meant as an alternative to the already existing Dojo library integration. Currently jQuery can be integrated into your Zend Framework applications in the following ways:

  • View helper to help setup the jQuery (Core and UI) environment

  • jQuery UI specific Zend_View helpers

  • jQuery UI specific Zend_Form elements and decorators

By default the jQuery javascript dependencies are loaded from the Google Ajax Library Content Distribution Network. The CDN offers both jQuery Core and jQuery UI access points and the view helpers therefore can already offer you most the dependencies out of the box. Currently the Google CDN offers jQuery UI support up to version 1.5.2, but the jQuery view and form helpers already make use of the UI library 1.6 version (AutoComplete, ColorPicker, Spinner, Slider). To make use of these great additions you have to download the release candidate version of the » jQuery UI library from its website.

ZendX_JQuery
ZendX_JQuery
Zend Framework手册 中文版
ZendX_JQuery View Helpers
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • ZendX_JQuery
  • Introduction
  • ZendX_JQuery View Helpers
  • ZendX_JQuery Form Elements and Decorators


ZendX_JQuery View Helpers - Zend Framework Manual

Introduction
ZendX_JQuery
Zend Framework手册 中文版
ZendX_JQuery Form Elements and Decorators

ZendX_JQuery View Helpers

Zend Framework provides jQuery related View Helpers through its Extras Library. These can be enabled in two ways, adding jQuery to the view helper path:

  1. $view->addHelperPath("ZendX/JQuery/View/Helper", "ZendX_JQuery_View_Helper");

Or using the ZendX_JQuery::enableView(Zend_View_Interface $view) method that does the same for you.

jQuery() View Helper

The jQuery() view helper simplifies setup of your jQuery environment in your application. It takes care of loading the core and ui library dependencies if necessary and acts as a stack for all the registered onLoad javascript statements. All jQuery view helpers put their javascript code onto this stack. It acts as a collector for everything jQuery in your application with the following responsibilities:

  • Handling deployment of CDN or a local path jQuery Core and UI libraries.

  • Handling $(document).onLoad() events.

  • Specifying additional stylesheet themes to use.

The jQuery() view helper implementation, like its dojo() pendant, follows the placeholder architecture implementation; the data set in it persists between view objects, and may be directly echo'd from your layout script. Since views specified in a Zend_Layout script file are rendered before the layout itself, the jQuery() helper can act as a stack for jQuery statements and render them into the head segment of the html page.

Contrary to Dojo, themes cannot be loaded from a CDN for the jQuery UI widgets and have to be implemented in your pages stylesheet file or loaded from an extra stylesheet file. A default theme called Flora can be obtained from the jQuery UI downloadable file.

Example #1 jQuery() View Helper Example

In this example a jQuery environment using the core and UI libraries will be needed. UI Widgets should be rendered with the Flora thema that is installed in 'public/styles/flora.all.css'. The jQuery libraries are both loaded from local paths.

To register the jQuery functionality inside the view object, you have to add the appropriate helpers to the view helper path. There are many ways of accomplishing this, based on the requirements that the jQuery helpers have. If you need them in one specific view only, you can use the addHelperPath method on initialization of this view, or right before rendering:

  1. $view->addHelperPath('ZendX/JQuery/View/Helper/', 'ZendX_JQuery_View_Helper');

If you need them throughout your application, you can register them in your bootstrap file using access to the Controller Plugin ViewRenderer:

  1. $view = new Zend_View();
  2. $view->addHelperPath('ZendX/JQuery/View/Helper/', 'ZendX_JQuery_View_Helper');
  3.
  4. $viewRenderer = new Zend_Controller_Action_Helper_ViewRenderer();
  5. $viewRenderer->setView($view);
  6. Zend_Controller_Action_HelperBroker::addHelper($viewRenderer);

Now in the view script we want to display a Date Picker and an Ajax based Link.

  1. <?php echo $this->ajaxLink("Show me something",
  2.                     "/hello/world",
  3.                     array('update' => '#content'));?>
  4.
  5. <div id="content"></div>
  6.
  7. <form method="post" action="/hello/world">
  8. Pick your Date: <?php echo $this->datePicker("dp1",
  9.                                              '',
  10.                                              array(
  11.                                                 'defaultDate' =>
  12.                                                     date('Y/m/d', time())));?>
  13. <input type="submit" value="Submit" />
  14. </form>

Both helpers now stacked some javascript statements on the jQuery helper and printed a link and a form element respectively. To access the javascript we have to utilize the jQuery() functionality. Both helpers already activated their dependencies that is they have called jQuery()->enable() and jQuery()->uiEnable(). We only have to print the jQuery() environment, and we choose to do so in the layout script's head segment:

  1. <html>
  2.     <head>
  3.         <title>A jQuery View Helper Example</title>
  4.         <?php echo $this->jQuery(); ?>
  5.     </head>
  6.
  7.     <body>
  8.         <?php echo $this->layout()->content; ?>
  9.     </body>
  10. </html>

Although $this->layout()->content; is printed behind the $this->jQuery() statement, the content of the view script is rendered before. This way all the javascript onLoad code has already been put on the onLoad stack and can be printed within the head segment of the html document.

jQuery NoConflict Mode

jQuery offers a noConflict mode that allows the library to be run side by side with other javascript libraries that operate in the global namespace, Prototype for example. The Zend Framework jQuery View Helper makes usage of the noConflict mode very easy. If you want to run Prototype and jQuery side by side you can call ZendX_JQuery_View_Helper_JQuery::enableNoConflictMode(); and all jQuery helpers will operate in the No Conflict Mode.

Example #2 Building your own Helper with No Conflict Mode

To make use of the NoConflict Mode in your own jQuery helper, you only have to use the static method ZendX_JQuery_View_Helper_JQuery::getJQueryHandler() method. It returns the variable jQuery is operating in at the moment, either $ or $j

  1. class MyHelper_SomeHelper extends Zend_View_Helper_Abstract
  2. {
  3.     public function someHelper()
  4.     {
  5.         $jquery = $this->view->jQuery();
  6.         $jquery->enable(); // enable jQuery Core Library
  7.
  8.         // get current jQuery handler based on noConflict settings
  9.         $jqHandler = ZendX_JQuery_View_Helper_JQuery::getJQueryHandler();
  10.
  11.         $function = '("#element").click(function() '
  12.                   . '{ alert("noConflict Mode Save Helper!"); }'
  13.                   . ')';
  14.         $jquery->addOnload($jqHandler . $function);
  15.         return '';
  16.     }
  17. }

jQuery UI Themes

Since there are no online available themes to use out of the box, the implementation of the UI library themes is a bit more complex than with the Dojo helper. The jQuery UI documentation describes for each component what stylesheet information is needed and the Default and Flora Themes from the downloadable archive give hints on the usage of stylesheets. The jQuery helper offers the function jQuery()->addStylesheet($path); function to include the dependant stylesheets whenever the helper is enabled and rendered. You can optionally merge the required stylesheet information in your main stylesheet file.

Methods Available

The jQuery() view helper always returns an instance of the jQuery placeholder container. That container object has the following methods available:

jQuery Core Library methods

  • enable(): explicitly enable jQuery integration.

  • disable(): disable jQuery integration.

  • isEnabled(): determine whether or not jQuery integration is enabled.

  • setVersion(): set the jQuery version that is used. This also decides on the library loaded from the Google Ajax Library CDN

  • getVersion(): get the current jQuery that is used. This also decides on the library loaded from the Google Ajax Library CDN

  • useCdn(): Return true, if CDN usage is currently enabled

  • useLocalPath(): Return true, if local usage is currently enabled

  • setLocalPath(): Set the local path to the jQuery Core library

  • getLocalPath(): If set, return the local path to the jQuery Core library

jQuery UI Library methods

  • uiEnable(): explicitly enable jQuery UI integration.

  • uiDisable(): disable jQuery UI integration.

  • uiIsEnabled(): determine whether or not jQuery UI integration is enabled.

  • setUiVersion(): set the jQuery UI version that is used. This also decides on the library loaded from the Google Ajax Library CDN

  • getUiVersion(): get the current jQuery UI that is used. This also decides on the library loaded from the Google Ajax Library CDN

  • useUiCdn(): Return true, if CDN usage is currently enabled for jQuery UI

  • useUiLocal(): Return true, if local usage is currently enabled for jQuery UI

  • setUiLocalPath(): Set the local path to the jQuery UI library

  • getUiLocalPath(): If set, get the local path to the jQuery UI library

jQuery Helper Utility methods

  • setView(Zend_View_Interface $view): set a view instance in the container.

  • onLoadCaptureStart(): Start capturing javascript code for jQuery onLoad execution.

  • onLoadCaptureEnd(): Stop capturing

  • javascriptCaptureStart(): Start capturing javascript code that has to be rendered after the inclusion of either jQuery Core or UI libraries.

  • javascriptCaptureEnd(): Stop capturing.

  • addJavascriptFile($path): Add javascript file to be included after jQuery Core or UI library.

  • getJavascriptFiles(): Return all currently registered additional javascript files.

  • clearJavascriptFiles(): Clear the javascript files

  • addJavascript($statement): Add javascript statement to be included after jQuery Core or UI library.

  • getJavascript(): Return all currently registered additional javascript statements.

  • clearJavascript(): Clear the javascript statements.

  • addStylesheet($path): Add a stylesheet file that is needed for a jQuery view helper to display correctly.

  • getStylesheets(): Get all currently registered additional stylesheets.

  • addOnLoad($statement): Add javascript statement that should be executed on document loading.

  • getOnLoadActions(): Return all currently registered onLoad statements.

  • setRenderMode($mask): Render only a specific subset of the jQuery environment via ZendX_JQuery::RENDER_ constants. Rendering all elements is the default behaviour.

  • getRenderMode(): Return the current jQuery environment rendering mode.

  • setCdnSsl($bool): Set if the CDN Google Ajax Library should be loaded from an SSL or a Non-SSL location.

These are quite a number of methods, but many of them are used for internally by all the additional view helpers and during the printing of the jQuery environment. Unless you want to build your own jQuery helper or have a complex use-case, you will probably only get in contact with a few methods of these.

Refactoring jQuery environment with setRenderMode()

Using the current setup that was described, each page of your website would show a different subset of jQuery code that would be needed to keep the current jQuery related items running. Also different files or stylesheets may be included depending on which helpers you implemented in your application. In production stage you might want to centralize all the javascript your application generated into a single file, or disable stylesheet rendering because you have merged all the stylesheets into a single file and include it statically in your layout. To allow a smooth refactoring you can enable or disable the rendering of certain jQuery environment blocks with help of the following constants and the jQuery()->setRenderMode($bitmask) function.

  • ZendX_JQuery::RENDER_LIBRARY: Renders jQuery Core and UI library

  • ZendX_JQuery::RENDER_SOURCES: Renders additional javascript files

  • ZendX_JQuery::RENDER_STYLESHEETS: Renders jQuery related stylesheets

  • ZendX_JQuery::RENDER_JAVASCRIPT: Render additional javascript statements

  • ZendX_JQuery::RENDER_JQUERY_ON_LOAD: Render jQuery onLoad statements

  • ZendX_JQuery::RENDER_ALL: Render all previously mentioned blocks, this is default behaviour.

For an example, if you would have merged jQuery Core and UI libraries as well as other files into a single large file as well as merged stylesheets to keep HTTP requests low on your production application. You could disallow the jQuery helper to render those parts, but render all the other stuff with the following statement in your view:

  1. $view->jQuery()
  2.      ->setRenderMode(ZendX_JQuery::RENDER_JAVASCRIPT |
  3.                      ZendX_JQuery::RENDER_JQUERY_ON_LOAD);

This statement makes sure only the required javascript statements and onLoad blocks of the current page are rendered by the jQuery helper.

Migrations

Prior to 1.8 the methods setCdnVersion(), setLocalPath() setUiCdnVersion() and setUiLocalPath() all enabled the view helper upon calling, which is considered a bug from the following perspective: If you want to use the any non-default library option, you would have to manually disable the jQuery helper aftwards if you only require it to be loaded in some scenarios. With version 1.8 the jQuery helper does only enable itsself, when enable() is called, which all internal jQuery View helpers do upon being called.

JQuery Helpers

AjaxLink Helper

The AjaxLink helper uses jQuery's ajax capabilities to offer the creation of links that do ajax requests and inject the response into a chosen DOM element. It also offers the possibility to append simple jQuery effects to both the link and the response DOM element. A simple example introduces its functionality:

  1. <!-- Inside your View Object -->
  2. <div id="container"></div>
  3. <?php echo $this->view->ajaxLink("Link Name",
  4.                           "url.php",
  5.                           array('update' => '#container')); ?>

This example creates a link with the label "Link Name" that fires an ajax request to url.php upon click and renders the response into the div container "#container". The function header for the ajaxLink is as follows: function ajaxLink($label, $url, $options, $params); The options array is very powerful and offers you lots of functionality to customize your ajax requests.

Available options are:

AjaxLink options
Option | Data Type | Default Value | Description
update | string | false | Container to inject response content into, use jQuery CSS Selector syntax, ie. "#container" or ".box"
method | string | Implicit GET or POST | Request method, is implicitly chosen as GET when no parameters given and POST when parameters given.
complete | string | false | Javascript callback executed, when ajax request is complete. This option allows for shortcut effects, see next section.
beforeSend | string | false | Javascript callback executed right before ajax request is started. This option allows for shortcut effects, see next section.
noscript | boolean | true | If true the link generated will contain a href attribute to the given link for non-javascript enabled browsers. If false href will resolve to "#".
dataType | string | html | What type of data is the Ajax Response of? Possible are Html, Text, Json. Processing Json responses has to be done with custom "complete" callback functions.
attribs | array | null | Additional HTML attributes the ajaxable link should have.
title, id, class | string | false | Convenience shortcuts for HTML Attributes.
inline | boolean | false | Although far from best practice, you can set javascript for this link inline in "onclick" attribute.

To enlighten the usage of this helper it is best to show another bunch of more complex examples. This example assumes that you have only one view object that you want to display and don't care a lot about html best practices, since we have to output the jQuery environment just before the closing body tag.

  1. <html>
  2.     <head>
  3.         <title>Zend Framework jQuery AjaxLink Example</title>
  4.         <script language="javascript"
  5.                 type="text/javascript"
  6.                 src="myCallbackFuncs.js"></script>
  7.     </head>
  8.
  9.     <body>
  10.         <!-- without echoing jQuery this following -->
  11.         <!-- list only prints a list of for links -->
  12.         <ul>
  13.             <li>
  14.                 <?php echo $this->ajaxLink("Example 1",
  15.                                            "/ctrl/action1",
  16.                                            array('update' => '#content',
  17.                                                  'noscript' => false,
  18.                                                  'method' => 'POST')); ?>
  19.             </li>
  20.             <li>
  21.                 <?php echo $this->ajaxLink("Example 2",
  22.                                            "/ctrl/action2",
  23.                                            array('update' => '#content',
  24.                                                  'class' => 'someLink'),
  25.                                            array('param1' => 'value1',
  26.                                                  'param2' => 'value2')); ?>
  27.             </li>
  28.             <li><?php echo $this->ajaxLink("Example 3",
  29.                                            "/ctrl/action3",
  30.                                            array('dataType' => 'json',
  31.                                                  'complete' =>
  32.                                                     'alert(data)')); ?>
  33.             </li>
  34.             <li><?php echo $this->ajaxLink("Example 4",
  35.                                            "/ctrl/action4",
  36.                                            array('beforeSend' => 'hide',
  37.                                                  'complete' => 'show')); ?>
  38.             </li>
  39.             <li>
  40.                 <?php echo $this->ajaxLink("Example 5",
  41.                                            "/ctrl/action5",
  42.                                            array(
  43.                                             'beforeSend' =>
  44.                                              'myBeforeSendCallbackJsFunc();',
  45.                                             'complete' =>
  46.                                              'myCompleteCallbackJsFunc(data);')
  47.                                            ); ?>
  48.             </li>
  49.         </ul>
  50.
  51.         <!-- only at this point the javascript is printed to sreen -->
  52.         <?php echo $this->jQuery(); ?>
  53.     </body>
  54. </html>

You might have already seen that the 'update', 'complete', and 'beforeSend' options have to be executed in specific order and syntax so that you cannot use those callbacks and override their behaviour completely when you are using ajaxLink(). For larger use cases you will probably want to write the request via jQuery on your own. The primary use case for the callbacks is effect usage, other uses may very well become hard to maintain. As shown in Example Link 5, you can also forward the beforeSend/complete Callbacks to your own javascript functions.

Shortcut Effects

You can use shortcut effect names to make your links actions more fancy. For example the Container that will contain the ajax response may very well be invisible in the first place. Additionally you can use shortcut effects on the link to hide it after clicking. The following effects can be used for callbacks:

  • complete callback: 'show', 'showslow', 'shownormal', 'showfast', 'fadein', 'fadeinslow', 'fadeinfast', 'slidedown', 'slidedownslow', 'slidedownfast'. These all correspond to the jQuery effects fadeIn(), show() and slideDown() and will be executed on the container specified in update.

  • beforeSend callback: 'fadeout', 'fadeoutslow', 'fadeoutfast', 'hide', 'hideslow', 'hidefast', 'slideup'. These correspond to the jQuery effects fadeOut(), hide(), slideUp() and are executed on the clicked link.

  1. <?php echo $this->ajaxLink("Example 6",
  2.                            "/ctrl/action6",
  3.                            array('beforeSend' => 'hide',
  4.                                  'complete' => 'show')); ?>

jQuery UI Library Helpers

The jQuery UI Library offers a range of layout and form specific widgets that are integrated into the Zend Framework via View Helpers. The form-elements are easy to handle and will be described first, whereas the layout specific widgets are a bit more complex to use.

jQuery UI Form Helpers

The method signature for all form view helpers closely resembles the Dojo View helpers signature, helper($id, $value, $params, $attribs). A description of the parameters follows:

  • $id: Will act as the identifier name for the helper element inside a form. If in the attributes no id element is given, this will also become the form element id, that has to be unique across the DOM.

  • $value: Default value of the element.

  • $params: Widget specific parameters that customize the look and feel of the widget. These options are unique to each widget and » described in the jQuery UI documentation. The data is casted to JSON, so make sure to use the Zend_Json_Expr class to mark executable javascript as safe.

  • $attribs: HTML Attributes of the Form Helper

The following UI widgets are available as form view helpers. Make sure you use the correct version of jQuery UI library to be able to use them. The Google CDN only offers jQuery UI up to version 1.5.2. Some other components are only available from jQuery UI SVN, since they have been removed from the announced 1.6 release.

  • autoComplete($id, $value, $params, $attribs): The AutoComplete View helper will be included in a future jQuery UI version (currently only via jQuery SVN) and creates a text field and registeres it to have auto complete functionality. The completion data source has to be given as jQuery related parameters 'url' or 'data' as described in the jQuery UI manual.

  • colorPicker($id, $value, $params, $attribs): ColorPicker is currently available in jQuery UI only from SVN and creates a text field that opens up a color picking tool when activated.

  • datePicker($id, $value, $params, $attribs): Create a DatePicker inside a text field. This widget is available since jQuery UI 1.5 and can therefore currently be used with the Google CDN. Using the 'handles' option to create multiple handles overwrites the default set value and the jQuery parameter 'startValue' internally inside the view helper.

  • slider($id, $value, $params, $attribs): Create a Sliding element that updates its value into a hidden form field. Available since jQuery UI 1.5.

  • spinner($id, $value, $params, $attribs): Create a Spinner element that can spin through numeric values in a specified range. This is set on top of a form text field and is available only from jQuery UI SVN

Example #3 Showing jQuery Form View Helper Usage

In this example we want to simulate a fictional web application that offers auctions on travel locations. A user may specify a city to travel, a start and end date, and a maximum amount of money he is willing to pay. Therefore we need an autoComplete field for all the currently known travel locations, a date picker for start and end dates and a spinner to specify the amount.

  1. <form method="post" action="bid.php">
  2.     <label for="locaction">Where do you want to travel?</label>
  3.     <?php echo $this->autoComplete("location",
  4.                                    "",
  5.                                    array('data' => array('New York',
  6.                                                          'Mexico City',
  7.                                                          'Sydney',
  8.                                                          'Ruegen',
  9.                                                          'Baden Baden'),
  10.                                          'multiple' => true)); ?>
  11.     <br />
  12.
  13.     <label for="startDate">Travel Start Date:</label>
  14.     <?php echo $this->datePicker("startDate", '',
  15.              array(
  16.                 'defaultDate' => '+7',
  17.                 'minDate' => '+7',
  18.                 'onClose' => new Zend_Json_Expr('myJsonFuncCechkingValidity'))); ?>
  19.     <br />
  20.
  21.     <label for="startDate">Travel End Date:</label>
  22.     <?php echo $this->datePicker("endDate", '',
  23.              array(
  24.                 'defaultDate' => '+14',
  25.                 'minDate' => '+7',
  26.                 'onClose' => new Zend_Json_Expr('myJsonFuncCechkingValidity'))); ?>
  27.     <br />
  28.
  29.     <label for="bid">Your Bid:</label>
  30.     <?php echo $this->spinner("bid",
  31.                               "",
  32.                               array('min' => 1205.50,
  33.                                     'max' => 10000,
  34.                                     'start' => 1205.50,
  35.                                     'currency' => '€')); ?>
  36.     <br />
  37.
  38.     <input type="submit" value="Bid!" />
  39. </form>

You can see the use of jQuery UI Widget specific parameters. These all correspond to those given in the jQuery UI docs and are converted to JSON and handed through to the view script.

Using an Action Helper to Send Data to AutoComplete

The jQuery UI Autocomplete Widget can load data from a remote location rather than from an javascript array, making its usage really useful. Zend Framework currently providers a bunch of server-side AutoComplete Helpers and there is one for jQuery too. You register the helper to the controller helper broker and it takes care of disabling layouts and renders an array of data correctly to be read by the AutoComplete field. To use the Action Helper you have to put this rather long statement into your bootstrap or Controller initialization function:

  1. Zend_Controller_Action_HelperBroker::addHelper(
  2.     new ZendX_JQuery_Controller_Action_Helper_AutoComplete()
  3. );

You can then directly call the helper to render AutoComplete Output in your Controller

  1. class MyIndexController extends Zend_Controller_Action
  2. {
  3.     public function autocompleteAction()
  4.     {
  5.         // The data sent via the ajax call is inside $_GET['q']
  6.         $filter = $_GET['q'];
  7.
  8.         // Disable Layout and stuff, just displaying AutoComplete Information.
  9.         $this->_helper->autoComplete(array("New York", "Bonn", "Tokio"));
  10.     }
  11. }

jQuery UI Layout Helpers

There is a wide range of Layout helpers that the UI library offers. The ones covered by Zend Framework view helpers are Accordion, Dialog, Tabs. Dialog is the most simple one, whereas Accordion and Tab extend a common abstract class and offer a secondary view helper for pane generation. The following view helpers exist in the jQuery view helpers collection, an example accompanies them to show their usage.

  • dialogContainer($id, $content, $params, $attribs): Create a Dialog Box that is rendered with the given content.on startup. If the option 'autoOpen' set to false is specified the box will not be displayed on load but can be shown with the additional dialog("open") javascript function. See UI docs for details.

  • tabPane($id, $content, $options): Add a new pane to a tab container with the given $id. The given $content is shown in this tab pane. To set the title use $options['title']. If $options['contentUrl'] is set, the content of the tab is requested via ajax on tab activation.

  • tabContainer($id, $params, $attribs): Render a tab container with all the currently registered panes. This view helper also offers to add panes with the following syntax: $this->tabContainer()->addPane($id, $label, $content, $options).

  • accordionPane($id, $content, $options): Add a new pane to the accordion container with the given $id. The given $content is shown in this tab pane. To set the title use $options['title'].

  • accordionContainer($id, $params, $attribs): Render an accordion container with all the currently registered panes. This view helper also offers to add panes with the following syntax: $this->accordionContainer()->addPane($id, $label, $content, $options).

Example #4 Showing the latest news in a Tab Container

For this example we assume the developer already wrote the controller and model side of the script and assigned an array of news items to the view script. This array contains at most 5 news elements, so we don't have to care about the tab container getting to many tabs.

  1. <?php foreach($this->news AS $article): ?>
  2. <?php $this->tabPane("newstab",
  3.                      $article->body,
  4.                      array('title' => $article->title)); ?>
  5. <?php endforeach; ?>
  6.
  7. <h2>Latest News</h2>
  8. <?php echo $this->tabContainer("newstab",
  9.                                array(),
  10.                                array('class' => 'flora')); ?>
Introduction
ZendX_JQuery
Zend Framework手册 中文版
ZendX_JQuery Form Elements and Decorators
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • ZendX_JQuery
  • Introduction
  • ZendX_JQuery View Helpers
  • ZendX_JQuery Form Elements and Decorators


ZendX_JQuery Form Elements and Decorators - Zend Framework Manual

ZendX_JQuery View Helpers
ZendX_JQuery
Zend Framework手册 中文版
系统需求

ZendX_JQuery Form Elements and Decorators

All View Helpers are pressed into Zend_Form elements or decorators also. They can even be easily integrated into your already existing forms. To enable a Form for Zend_JQuery support you can use two ways: Init your form as $form = new ZendX_JQuery_Form(); or use the static method ZendX_JQuery::enableForm($form) to enable jQuery element support.

General Elements and Decorator Usage

Both elements and decorators of the Zend jQuery Form set can be initialized with the option key jQueryParams to set certain jQuery object related parameters. This jQueryParams array of options matches to the $params variable of the corresponding view helpers. For example:

  1. $element = new ZendX_JQuery_Form_Element_DatePicker(
  2.                     'dp1',
  3.                     array('jQueryParams' => array('defaultDate' => '2007/10/10'))
  4.                 );
  5. // would internally call to:
  6. $view->datePicker("dp1", "", array('defaultDate' => '2007/10/10'), array());

Additionally elements jQuery options can be customized by the following methods:

  • setJQueryParam($name, $value): Set the jQuery option $name to the given value.

  • setJQueryParams($params): Set key value pairs of jQuery options and merge them with the already set options.

  • getJQueryParam($name): Return the jQuery option with the given name.

  • getJQueryParams(): Return an array of all currently set jQuery options.

Each jQuery related Decorator also owns a getJQueryParams() method, to set options you have to use the setDecorators(), addDecorator() or addDecorators() functionality of a form element and set the jQueryParams key as option:

  1. $form->setDecorators(array(
  2.     'FormElements',
  3.     array('AccordionContainer', array(
  4.         'id'          => 'tabContainer',
  5.         'style'       => 'width: 600px;',
  6.         'jQueryParams' => array(
  7.             'alwaysOpen' => false,
  8.             'animated'   => "easeslide"
  9.         ),
  10.     )),
  11.     'Form'
  12. ));

Form Elements

The Zend Framework jQuery Extras Extension comes with the following Form Elements:

  • ZendX_JQuery_Form_Element_AutoComplete: Proxy to AutoComplete View Helper

  • ZendX_JQuery_Form_Element_ColorPicker: Proxy to ColorPicker View Helper

  • ZendX_JQuery_Form_Element_DatePicker: Proxy to DatePicker View Helper

  • ZendX_JQuery_Form_Element_Slider: Proxy to Slider View Helper

  • ZendX_JQuery_Form_Element_Spinner: Proxy to Spinner View Helper

Note: jQuery Decorators: Beware the Marker Interface for UiWidgetElements
 By default all the jQuery Form elements use the ZendX_JQuery_Form_Decorator_UiWidgetElement decorator for rendering the jQuery element with its specific view helper. This decorator is inheritly different from the ViewHelper decorator that is used for most of the default form elements in Zend_Form. To ensure that rendering works correctly for jQuery form elements at least one decorator has to implement the ZendX_JQuery_Form_Decorator_UiWidgetElementMarker interface, which the default decorator does. If no marker interface is found an exception is thrown. Use the marker interface if you want to implement your own decorator for the jQuery form element specific rendering.

Form Decorators

The following Decorators come with the Zend Framework jQuery Extension:

  • ZendX_JQuery_Form_Decorator_AccordionContainer: Proxy to AccordionContainer View Helper

  • ZendX_JQuery_Form_Decorator_AccordionPane: Proxy to AccordionPane View Helper

  • ZendX_JQuery_Form_Decorator_DialogContainer: Proxy to DialogContainer View Helper

  • ZendX_JQuery_Form_Decorator_TabContainer: Proxy to TabContainer View Helper

  • ZendX_JQuery_Form_Decorator_TabPane: Proxy to TabPane View Helper

  • ZendX_JQuery_Form_Decorator_UiWidgetElement: Decorator to Display jQuery Form Elements

Utilizing the Container elements is a bit more complicated, the following example builds a Form with 2 SubForms in a TabContainer:

Example #1 SubForms with TabContainer Decorator

The following example makes use of all Form elements and wraps them into 2 subforms that are decorated with a tab container. First we build the basic ZendX_JQuery_Form:

  1. $form = new ZendX_JQuery_Form();
  2. $form->setAction('formdemo.php');
  3. $form->setAttrib('id', 'mainForm');
  4. $form->setAttrib('class', 'flora');
  5.
  6. $form->setDecorators(array(
  7.     'FormElements',
  8.     array('TabContainer', array(
  9.         'id'          => 'tabContainer',
  10.         'style'       => 'width: 600px;',
  11.     )),
  12.     'Form',
  13. ));

Setting the Form Id (in this case to 'mainForm') is an important step for the TabContainer. It is needed that the subforms can relate to the Container Id in a later form building stage. We now initialize two SubForms that will be decorated with the TabPane decorators:

  1. $subForm1 = new ZendX_JQuery_Form();
  2. $subForm1->setDecorators(array(
  3.     'FormElements',
  4.     array('HtmlTag',
  5.           array('tag' => 'dl')),
  6.     array('TabPane',
  7.           array('jQueryParams' => array('containerId' => 'mainForm',
  8.                                         'title' => 'DatePicker and Slider')))
  9. ));
  10.
  11. $subForm2 = new ZendX_JQuery_Form();
  12. $subForm2->setDecorators(array(
  13.    'FormElements',
  14.    array('HtmlTag',
  15.          array('tag' => 'dl')),
  16.    array('TabPane',
  17.          array('jQueryParams' => array('containerId' => 'mainForm',
  18.                                        'title' => 'AutoComplete and Spinner')))
  19. ));

In this stage it is important that the 'containerId' option is set in each SubForm TabPane, or the subforms cannot relate back to the tab Container and would not be displayed. To enforce this setting, an exception of the type ZendX_JQuery_Exception is thrown if the option is not set. We can now add all the desired elements to the subforms:

  1. // Add Element Date Picker
  2. $elem = new ZendX_JQuery_Form_Element_DatePicker(
  3.                 "datePicker1", array("label" => "Date Picker:")
  4.             );
  5. $elem->setJQueryParam('dateFormat', 'dd.mm.yy');
  6. $subForm1->addElement($elem);
  7.
  8. // Add Element Spinner
  9. $elem = new ZendX_JQuery_Form_Element_Spinner(
  10.                 "spinner1", array('label' => 'Spinner:')
  11.             );
  12. $elem->setJQueryParams(array('min' => 0, 'max' => 1000, 'start' => 100));
  13. $subForm1->addElement($elem);
  14.
  15. // Add Slider Element
  16. $elem = new ZendX_JQuery_Form_Element_Slider(
  17.                 "slider1", array('label' => 'Slider:')
  18.             );
  19. $elem->setJQueryParams(array('defaultValue' => '75'));
  20. $subForm2->addElement($elem);
  21.
  22. // Add Autocomplete Element
  23. $elem = new ZendX_JQuery_Form_Element_AutoComplete(
  24.                 "ac1", array('label' => 'Autocomplete:')
  25.             );
  26. $elem->setJQueryParams(array('data' => array('New York',
  27.                                              'Berlin',
  28.                                              'Bern',
  29.                                              'Boston')));
  30. $subForm2->addElement($elem);
  31.
  32. // Submit Button
  33. $elem = new Zend_Form_Element_Submit("btn1", array('value' => 'Submit'));
  34. $subForm1->addElement($elem);

Three additional lines are missing to put it all together and we have a jQuery animated form:

  1. $form->addSubForm($subForm1, 'subform1');
  2. $form->addSubForm($subForm2, 'subform2');
  3.
  4. $formString = $form->render($view);
ZendX_JQuery View Helpers
ZendX_JQuery
Zend Framework手册 中文版
系统需求
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • ZendX_JQuery
  • Introduction
  • ZendX_JQuery View Helpers
  • ZendX_JQuery Form Elements and Decorators


系统需求 - Zend Framework Manual

ZendX_JQuery Form Elements and Decorators
PHP 版本需求

系统需求

Table of Contents
  • PHP 版本需求
  • PHP 扩展
  • Zend Framework 组件

这部分描述了 Zend Framework 对系统的需求。

ZendX_JQuery Form Elements and Decorators
Zend Framework手册 中文版
Zend Framework手册 中文版
PHP 版本需求
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework简介
  • Learning Zend Framework
  • Zend Framework Reference
  • 系统需求
  • Zend Framework Migration Notes
  • Zend Framework 的 PHP 编码标准
  • Zend Framework Documentation Standard
  • Recommended Project Structure for Zend Framework MVC Applications
  • Zend Framework Performance Guide
  • 版权信息


PHP 版本需求 - Zend Framework Manual

系统需求
系统需求
Zend Framework手册 中文版
PHP 扩展

PHP 版本需求

Zend Framework 需要 PHP 5.1.4 或更高版本。例如 Countable 这样一些 SPL 接口在 PHP 之前的版本中没有被正式使用。

Zend Framework 提供了大量自动化测试，可以使用 PHPUnit 3.0 或更高版本运行。 这个版本的 PHPUnit 同样也需要 PHP 5.1.4 或更高版本。

虽然 Zend Framework 可以在上面提到的 PHP 版本下正确工作，但是强烈建议使用 PHP 5.2.2 或更高版本。 新版本的 PHP 有许多重要的安全更新和性能提升。

系统需求
系统需求
Zend Framework手册 中文版
PHP 扩展
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • 系统需求
  • PHP 版本需求
  • PHP 扩展
  • Zend Framework 组件


PHP 扩展 - Zend Framework Manual

PHP 版本需求
系统需求
Zend Framework手册 中文版
Zend Framework 组件

PHP 扩展

下面列出了所有 PHP 内建支持的扩展，以及它们在 Zend Framework 中如何应用。 这个可以帮助了解哪个扩展需要在应用中使用。 不是每一个被 Zend Framework 使用的扩展都要应用在程序中。

使用方式“依赖”表示当扩展不可用时，组件或者类也不可使用。 使用方式“可选”表示当扩展不可用时，组件或者类自动使用代替方案。

Zend Framework 使用的 PHP 扩展
扩展 | 使用方式 | 使用扩展的 Zend Framework 组件
» apc | 依赖 | » Zend_Cache_Backend_Apc
» bcmath | 可选 | » Zend_Locale_Math
» bitset | 可选 | » Zend_Search_Lucene
» bz2 | -- |
» calendar | -- |
» com_dotnet | -- |
» ctype | 依赖 | » Zend_Auth_Adapter_Http, » Zend_Gdata_App, » Zend_Http_Client, » Zend_Pdf, » Zend_Rest_Client, » Zend_Rest_Server, » Zend_Search_Lucene, » Zend_Uri, » Zend_Validate
» curl | 依赖 | » Zend_Http_Client_Adapter_Curl
» date | --- |
» dba | -- |
» dbase | -- |
» dom | 依赖 | » Zend_Feed, » Zend_Gdata, » Zend_Log_Formatter_Xml, » Zend_Rest_Server, » Zend_Search_Lucene, » Zend_Service_Amazon, » Zend_Service_Delicious, » Zend_Service_Flickr, » Zend_Service_Simpy, » Zend_Service_Yahoo, » Zend_XmlRpc
» exif | -- |
» fbsql | -- |
» fdf | -- |
» filter | -- |
» ftp | -- |
» gd | 依赖 | » Zend_Pdf
» gettext | -- |
» gmp | -- |
» hash | 依赖 | » Zend_Auth_Adapter_Http
» ibm_db2 | 依赖 | » Zend_Db_Adapter_Db2
» iconv | 依赖 | » Zend_Locale_Format, » Zend_Mime_Decode, » Zend_Pdf, » Zend_Search_Lucene, » Zend_Service_Audioscrobbler, » Zend_Service_Flickr, » Zend_XmlRpc_Client
» imap | -- |
» informix | -- |
» interbase | 依赖 | Zend_Db_Adapter_Firebird
» json | 可选 | » Zend_Json
» ldap | -- |
» libxml | 依赖 | » DOM, » SimpleXML, » XSLT
» mbstring | 依赖 | » Zend_Feed
» mcrypt | -- |
» memcache | 依赖 | » Zend_Cache_Backend_Memcached
» mhash | -- |
» mime_magic | 依赖 | » Zend_Http_Client
» ming | -- |
» msql | -- |
» mssql | -- |
» mysql | -- |
» mysqli | 依赖 | » Zend_Db_Adapter_Mysqli
» ncurses | -- |
» oci8 | 依赖 | » Zend_Db_Adapter_Oracle
» odbc | -- |
» openssl | -- |
» pcntl | -- |
» pcre | 依赖 | Virtually all components
» pdo | 依赖 | All PDO database adapters
» pdo_dblib | -- |
» pdo_firebird | -- |
pdo_mssql | 依赖 | » Zend_Db_Adapter_Pdo_Mssql
» pdo_mysql | 依赖 | » Zend_Db_Adapter_Pdo_Mysql
» pdo_oci | 依赖 | » Zend_Db_Adapter_Pdo_Oci
» pdo_pgsql | 依赖 | » Zend_Db_Adapter_Pdo_Pgsql
» pdo_sqlite | 依赖 | » Zend_Db_Adapter_Pdo_Sqlite
» pgsql | --- |
» posix | 可选 | » Zend_Mail
» pspell | --- |
» readline | --- |
» recode | --- |
» Reflection | 依赖 | » Zend_Controller, » Zend_Filter, » Zend_Filter_Input, » Zend_Json, » Zend_Log, » Zend_Rest_Server, » Zend_Server_Reflection, » Zend_Validate, » Zend_View, » Zend_XmlRpc_Server
» session | 依赖 | » Zend_Controller_Action_Helper_Redirector, » Zend_Session
» shmop | --- |
» SimpleXML | 依赖 | » Zend_Config_Xml, » Zend_Feed, » Zend_Rest_Client, » Zend_Service_Audioscrobbler, » Zend_XmlRpc
» soap | 依赖 | » Zend_Service_StrikeIron
» sockets | --- |
» SPL | 依赖 | Virtually all components
» SQLite | 依赖 | » Zend_Cache_Backend_Sqlite
standard | 依赖 | Virtually all components
» sybase | --- |
sysvmsg | --- |
sysvsem | --- |
sysvshm | --- |
» tidy | --- |
» tokenizer | --- |
» wddx | --- |
» xml | 依赖 | » Zend_Translate_Adapter_Qt, » Zend_Translate_Adapter_Tmx, » Zend_Translate_Adapter_Xliff
» XMLReader | --- |
» xmlrpc | --- |
» XMLWriter | --- |
» xsl | --- |
» zip | --- |
» zlib | 依赖 | » Zend_Pdf, » Memcache
PHP 版本需求
系统需求
Zend Framework手册 中文版
Zend Framework 组件
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • 系统需求
  • PHP 版本需求
  • PHP 扩展
  • Zend Framework 组件


Zend Framework 组件 - Zend Framework Manual

PHP 扩展
系统需求
Zend Framework手册 中文版
Zend Framework Migration Notes

Zend Framework 组件

下面的表格列出了所有可用的 Zend Framework 组件，以及其所需的 PHP 扩展。这可以帮助了解哪些扩展对于应用来说是必须的。并不是每个应用都需要所有 Zend Framework 使用到的扩展。

Zend Framework 组件以及其使用到的 PHP 扩展
Zend Framework 组件 | PHP 扩展 （子类 / 使用方式）
所有组件 | » pcre ( 依赖 ) » SPL ( 依赖 ) standard ( 依赖 )
» Zend_Acl | ---
» Zend_Auth | » ctype ( » Zend_Auth_Adapter_Http / 依赖 ) » hash ( » Zend_Auth_Adapter_Http / 依赖 )
» Zend_Cache | » apc ( » Zend_Cache_Backend_Apc / 依赖 ) » memcache ( » Zend_Cache_Backend_Memcache / 依赖 ) » sqlite ( » Zend_Cache_Backend_Sqlite / 依赖 ) » zlib ( » Zend_Cache_Backend_Zlib / 依赖 )
» Zend_Config | » libxml ( » Zend_Config_Xml / 依赖 ) » SimpleXML ( » Zend_Config_Xml / 依赖 )
» Zend_Console_Getopt | ---
» Zend_Controller | » Reflection ( 依赖 ) » session ( » Zend_Controller_Action_Helper_Redirector / 依赖 )
» Zend_Date | ---
» Zend_Db | » ibm_db2 ( » Zend_Db_Adapter_Db2 / 依赖 ) » mysqli ( » Zend_Db_Adapter_Mysqli / 依赖 ) » oci8 ( » Zend_Db_Adapter_Oracle / 依赖 ) » pdo ( All PDO Adapters / 依赖 ) pdo_mssql ( » Zend_Db_Adapter_Pdo_Mssql / 依赖 ) » pdo_mysql ( » Zend_Db_Adapter_Pdo_Mysql / 依赖 ) » pdo_oci ( » Zend_Db_Adapter_Pdo_Oci / 依赖 ) » pdo_pgsql ( » Zend_Db_Adapter_Pdo_Pgsql / 依赖 ) » pdo_sqlite ( » Zend_Db_Adapter_Pdo_Sqlite / 依赖 )
» Zend_Debug | ---
» Zend_Exception | ---
» Zend_Feed | » dom ( 依赖 ) » libxml ( 依赖 ) » mbstring ( 依赖 ) » SimpleXML ( 依赖 )
» Zend_Filter | » Reflection ( 依赖 )
» Zend_Filter_Input | » Reflection ( 依赖 )
» Zend_Gdata | » ctype ( » Zend_Gdata_App / 依赖 ) » dom ( 依赖 ) » libxml ( 依赖 )
» Zend_Http | » ctype ( » Zend_Http_Client / 依赖 ) » curl ( » Zend_Http_Client_Adapter_Curl / 依赖 ) » mime_magic ( » Zend_Http_Client / 依赖 )
» Zend_Json | » json ( 可选 ) » Reflection ( 依赖 )
» Zend_Loader | ---
» Zend_Locale | » bcmath ( » Zend_Locale_Math / 可选 ) » iconv ( » Zend_Locale_Format / 依赖 )
» Zend_Log | » dom ( » Zend_Log_Formatter_Xml / 依赖 ) » libxml ( » Zend_Log_Formatter_Xml / 依赖 ) » Reflection ( 依赖 )
» Zend_Mail | » posix ( 可选 )
» Zend_Measure | ---
» Zend_Memory | ---
» Zend_Mime | » iconv ( » Zend_Mime_Decode / 依赖 )
» Zend_Pdf | » ctype ( 依赖 ) » gd ( 依赖 ) » iconv ( 依赖 ) » zlib ( 依赖 )
» Zend_Registry | ---
Zend_Request | ---
» Zend_Rest | » ctype ( » Zend_Rest_Client / 依赖 ) ( » Zend_Rest_Server / 依赖 ) » dom ( » Zend_Rest_Server / 依赖 ) » libxml ( » Zend_Rest_Client / 依赖 ) ( » Zend_Rest_Server / 依赖 ) » Reflection ( » Zend_Rest_Server / 依赖 ) » SimpleXML ( » Zend_Rest_Client / 依赖 )
» Zend_Search_Lucene | » ctype ( 依赖 ) » bitset ( 可选 ) » dom ( 依赖 ) » iconv ( 依赖 ) » libxml ( 依赖 )
» Zend_Server_Reflection | » Reflection ( 依赖 )
» Zend_Service_Akismet | ---
» Zend_Service_Amazon | » dom ( 依赖 ) » libxml ( 依赖 )
» Zend_Service_Audioscrobbler | » iconv ( 依赖 ) » libxml ( 依赖 ) » SimpleXML ( 依赖 )
» Zend_Service_Delicious | » dom ( 依赖 ) » libxml ( 依赖 )
» Zend_Service_Flickr | » dom ( 依赖 ) » iconv ( 依赖 ) » libxml ( 依赖 )
» Zend_Service_Simpy | » dom ( 依赖 ) » libxml ( 依赖 ) » libxml ( 依赖 )
» Zend_Service_StrikeIron | » soap ( 依赖 )
» Zend_Service_Yahoo | » dom ( 依赖 ) » libxml ( 依赖 )
» Zend_Session | » session ( 依赖 )
» Zend_Translate | » xml ( » Zend_Translate_Adapter_Qt / 依赖 ) ( » Zend_Translate_Adapter_Tmx / 依赖 ) ( » Zend_Translate_Adapter_Xliff / 依赖 )
» Zend_Uri | » ctype ( 依赖 )
» Zend_Validate | » ctype ( 依赖 ) » Reflection ( 依赖 )
» Zend_Version | ---
» Zend_View | » Reflection ( 依赖 )
» Zend_XmlRpc | » dom ( 依赖 ) » iconv ( » Zend_XmlRpc_Client / 依赖 ) » libxml ( 依赖 ) » Reflection ( » Zend_XmlRpc_Server / 依赖 ) » SimpleXML ( 依赖 )
PHP 扩展
系统需求
Zend Framework手册 中文版
Zend Framework Migration Notes
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • 系统需求
  • PHP 版本需求
  • PHP 扩展
  • Zend Framework 组件


Zend Framework Migration Notes - Zend Framework Manual

Zend Framework 组件
Zend Framework 1.10

Zend Framework Migration Notes

Table of Contents
  • Zend Framework 1.10
  • Zend Framework 1.9
  • Zend Framework 1.8
  • Zend Framework 1.7
  • Zend Framework 1.6
  • Zend Framework 1.5
  • Zend Framework 1.0
  • Zend Framework 0.9
  • Zend Framework 0.8
  • Zend Framework 0.6
Zend Framework 组件
Zend Framework手册 中文版
Zend Framework手册 中文版
Zend Framework 1.10
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework简介
  • Learning Zend Framework
  • Zend Framework Reference
  • 系统需求
  • Zend Framework Migration Notes
  • Zend Framework 的 PHP 编码标准
  • Zend Framework Documentation Standard
  • Recommended Project Structure for Zend Framework MVC Applications
  • Zend Framework Performance Guide
  • 版权信息


Zend Framework 1.10 - Zend Framework Manual

Zend Framework Migration Notes
Zend Framework Migration Notes
Zend Framework手册 中文版
Zend Framework 1.9

Zend Framework 1.10

When upgrading from a previous release to Zend Framework 1.10 or higher you should note the following migration notes.

Zend_Controller_Front

A wrong behaviour was fixed, when there was no module route and no route matched the given request. Previously, the router returned an unmodified request object, so the front controller just displayed the default controller and action. Since Zend Framework 1.10, the router will correctly as noted in the router interface, throw an exception if no route matches. The error plugin will then catch that exception and forward to the error controller. You can then test for that specific error with the constant :

  1. /**
  2. * Before 1.10
  3. */
  4.     public function errorAction()
  5.     {
  6.         $errors = $this->_getParam('error_handler');
  7.
  8.         switch ($errors->type) {
  9.             case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER:
  10.             case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION:
  11.     // ...
  12.
  13. /**
  14. * With 1.10
  15. */
  16.     public function errorAction()
  17.     {
  18.         $errors = $this->_getParam('error_handler');
  19.
  20.         switch ($errors->type) {
  21.             case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ROUTE:
  22.             case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER:
  23.             case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION:
  24.     // ...

Zend_Feed_Reader

With the introduction of Zend Framework 1.10, Zend_Feed_Reader's handling of retrieving Authors and Contributors was changed, introducing a break in backwards compatibility. This change was an effort to harmonise the treatment of such data across the RSS and Atom classes of the component and enable the return of Author and Contributor data in more accessible, usable and detailed form. It also rectifies an error in that it was assumed any author element referred to a name. In RSS this is incorrect as an author element is actually only required to provide an email address. In addition, the original implementation applied its RSS limits to Atom feeds significantly reducing the usefulness of the parser with that format.

The change means that methods like getAuthors() and getContributors no longer return a simple array of strings parsed from the relevant RSS and Atom elements. Instead, the return value is an ArrayObject subclass called Zend_Feed_Reader_Collection_Author which simulates an iterable multidimensional array of Authors. Each member of this object will be a simple array with three potential keys (as the source data permits). These include: name, email and uri.

The original behaviour of such methods would have returned a simple array of strings, each string attempting to present a single name, but in reality this was unreliable since there is no rule governing the format of RSS Author strings.

The simplest method of simulating the original behaviour of these methods is to use the Zend_Feed_Reader_Collection_Author's getValues() which also returns a simple array of strings representing the "most relevant data", for authors presumed to be their name. Each value in the resulting array is derived from the "name" value attached to each Author (if present). In most cases this simple change is easy to apply as demonstrated below.

  1. /**
  2. * Before 1.10
  3. */
  4. $feed = Zend_Feed_Reader::import('http://example.com/feed');
  5. $authors = $feed->getAuthors();
  6.
  7. /**
  8. * With 1.10
  9. */
  10. $feed = Zend_Feed_Reader::import('http://example.com/feed');
  11. $authors = $feed->getAuthors()->getValues();

Zend_File_Transfer

Security change

For security reasons Zend_File_Transfer does no longer store the original mimetype and filesize which is given from the requesting client into its internal storage. Instead the real values will be detected at initiation.

Additionally the original values within $_FILES will be overridden within the real values at initiation. This makes also $_FILES secure.

When you are in need of the original values you can eighter store them before initiating Zend_File_Transfer or use the disableInfos option at initiation. Note that this option is useless when its given after initiation.

Count validation

Before release 1.10 the MimeType validator used a wrong naming. For consistency the following constants have been changed:

Changed Validation Messages
Old | New | Value
TOO_MUCH | TOO_MANY | Too many files, maximum '%max%' are allowed but '%count%' are given
TOO_LESS | TOO_FEW | Too few files, minimum '%min%' are expected but '%count%' are given

When you are translating these messages within your code then use the new constants. As benefit you don't need to translate the original string anymore to get a correct spelling.

Zend_Filter_HtmlEntities

In order to default to a more secure character encoding, Zend_Filter_HtmlEntities now defaults to UTF-8 instead of ISO-8859-1.

Additionally, because the actual mechanism is dealing with character encodings and not character sets, two new methods have been added, setEncoding() and getEncoding(). The previous methods setCharSet() and setCharSet() are now deprecated and proxy to the new methods. Finally, instead of using the protected members directly within the filter() method, these members are retrieved by their explicit accessors. If you were extending the filter in the past, please check your code and unit tests to ensure everything still continues to work.

Zend_Filter_StripTags

Zend_Filter_StripTags contains a flag, commentsAllowed, that, in previous versions, allowed you to optionally whitelist HTML comments in HTML text filtered by the class. However, this opens code enabling the flag to XSS attacks, particularly in Internet Explorer (which allows specifying conditional functionality via HTML comments). Starting in version 1.9.7 (and backported to versions 1.8.5 and 1.7.9), the commentsAllowed flag no longer has any meaning, and all HTML comments, including those containing other HTML tags or nested commments, will be stripped from the final output of the filter.

Zend_Translate

Xliff adapter

In past the Xliff adapter used the source string as message Id. According to the Xliff standard the trans-unit Id should be used. This behaviour was corrected with Zend Framework 1.10. Now the trans-unit Id is used as message Id per default.

But you can still get the incorrect and old behaviour by setting the useId option to FALSE.

  1. $trans = new Zend_Translate('xliff', '/path/to/source', $locale, array('useId' => false));

Zend_Validate

Self written validators

When setting returning a error from within a self written validator you have to call the _error() method. Before Zend Framework 1.10 you were able to call this method without giving a parameter. It used then the first found message template.

This behaviour is problematic when you have validators with more than one different message to be returned. Also when you extend an existing validator you can get unexpected results. This could lead to the problem that your user get not the message you expected.

  1. My_Validator extends Zend_Validate_Abstract
  2. {
  3.     public isValid($value)
  4.     {
  5.         ...
  6.         $this->_error(); // unexpected results between different OS
  7.         ...
  8.     }
  9. }

To prevent this problem the _error() method is no longer allowed to be called without giving a parameter.

  1. My_Validator extends Zend_Validate_Abstract
  2. {
  3.     public isValid($value)
  4.     {
  5.         ...
  6.         $this->_error(self::MY_ERROR); // defined error, no unexpected results
  7.         ...
  8.     }
  9. }

Simplification in date validator

Before Zend Framework 1.10 2 identical messages were thrown within the date validator. These were NOT_YYYY_MM_DD and FALSEFORMAT. As of Zend Framework 1.10 only the FALSEFORMAT message will be returned when the given date does not match the set format.

Fixes in Alpha, Alnum and Barcode validator

Before Zend Framework 1.10 the messages within the 2 barcode adapters, the Alpha and the Alnum validator were identical. This introduced problems when using custom messages, translations or multiple instances of these validators.

As with Zend Framework 1.10 the values of the constants were changed to be unique. When you used the constants as proposed in the manual there is no change for you. But when you used the content of the constants in your code then you will have to change them. The following table shows you the changed values:

Available Validation Messages
Validator | Constant | Value
Alnum | STRING_EMPTY | alnumStringEmpty
Alpha | STRING_EMPTY | alphaStringEmpty
Barcode_Ean13 | INVALID | ean13Invalid
Barcode_Ean13 | INVALID_LENGTH | ean13InvalidLength
Barcode_UpcA | INVALID | upcaInvalid
Barcode_UpcA | INVALID_LENGTH | upcaInvalidLength
Digits | STRING_EMPTY | digitsStringEmpty
Zend Framework Migration Notes
Zend Framework Migration Notes
Zend Framework手册 中文版
Zend Framework 1.9
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Migration Notes
  • Zend Framework 1.10
  • Zend Framework 1.9
  • Zend Framework 1.8
  • Zend Framework 1.7
  • Zend Framework 1.6
  • Zend Framework 1.5
  • Zend Framework 1.0
  • Zend Framework 0.9
  • Zend Framework 0.8
  • Zend Framework 0.6


Zend Framework 1.9 - Zend Framework Manual

Zend Framework 1.10
Zend Framework Migration Notes
Zend Framework手册 中文版
Zend Framework 1.8

Zend Framework 1.9

When upgrading from a release of Zend Framework earlier than 1.9.0 to any 1.9 release, you should note the following migration notes.

Zend_File_Transfer

MimeType validation

For security reasons we had to turn off the default fallback mechanism of the MimeType, ExcludeMimeType, IsCompressed and IsImage validators. This means, that if the fileInfo or magicMime extensions can not be found, the validation will always fail.

If you are in need of validation by using the HTTP fields which are provided by the user then you can turn on this feature by using the enableHeaderCheck() method.

Note: Security hint
 You should note that relying on the HTTP fields, which are provided by your user, is a security risk. They can easily be changed and could allow your user to provide a malcious file.

Example #1 Allow the usage of the HTTP fields

  1. // at initiation
  2. $valid = new Zend_File_Transfer_Adapter_Http(array('headerCheck' => true);
  3.
  4. // or afterwards
  5. $valid->enableHeaderCheck();

Zend_Filter

Prior to the 1.9 release, Zend_Filter allowed the usage of the static get() method. As with release 1.9 this method has been renamed to filterStatic() to be more descriptive. The old get() method is marked as deprecated.

Zend_Http_Client

Changes to internal uploaded file information storage

In version 1.9 of Zend Framework, there has been a change in the way Zend_Http_Client internally stores information about files to be uploaded, set using the Zend_Http_Client::setFileUpload() method.

This change was introduced in order to allow multiple files to be uploaded with the same form name, as an array of files. More information about this issue can be found in » this bug report.

Example #2 Internal storage of uploaded file information

  1. // Upload two files with the same form element name, as an array
  2. $client = new Zend_Http_Client();
  3. $client->setFileUpload('file1.txt',
  4.                        'userfile[]',
  5.                        'some raw data',
  6.                        'text/plain');
  7. $client->setFileUpload('file2.txt',
  8.                        'userfile[]',
  9.                        'some other data',
  10.                        'application/octet-stream');
  11.
  12. // In Zend Framework 1.8 or older, the value of
  13. // the protected member $client->files is:
  14. // $client->files = array(
  15. //     'userfile[]' => array('file2.txt',
  16.                              'application/octet-stream',
  17.                              'some other data')
  18. // );
  19.
  20. // In Zend Framework 1.9 or newer, the value of $client->files is:
  21. // $client->files = array(
  22. //     array(
  23. //         'formname' => 'userfile[]',
  24. //         'filename' => 'file1.txt,
  25. //         'ctype'    => 'text/plain',
  26. //         'data'     => 'some raw data'
  27. //     ),
  28. //     array(
  29. //         'formname' => 'userfile[]',
  30. //         'filename' => 'file2.txt',
  31. //         'formname' => 'application/octet-stream',
  32. //         'formname' => 'some other data'
  33. //     )
  34. // );

As you can see, this change permits the usage of the same form element name with more than one file - however, it introduces a subtle backwards-compatibility change and as such should be noted.

Deprecation of Zend_Http_Client::_getParametersRecursive()

Starting from version 1.9, the protected method _getParametersRecursive() is no longer used by Zend_Http_Client and is deprecated. Using it will cause an E_NOTICE message to be emitted by PHP.

If you subclass Zend_Http_Client and call this method, you should look into using the Zend_Http_Client::_flattenParametersArray() static method instead.

Again, since this _getParametersRecursive() is a protected method, this change will only affect users who subclass Zend_Http_Client.

Zend_Locale

Depreciated methods

Some specialized translation methods have been depreciated because they duplicate existing behaviour. Note that the old methods will still work, but a user notice is triggered which describes the new call. The methods will be erased with 2.0. See the following list for old and new method call.

List of measurement types
Old call | New call
getLanguageTranslationList($locale) | getTranslationList('language', $locale)
getScriptTranslationList($locale) | getTranslationList('script', $locale)
getCountryTranslationList($locale) | getTranslationList('territory', $locale, 2)
getTerritoryTranslationList($locale) | getTranslationList('territory', $locale, 1)
getLanguageTranslation($value, $locale) | getTranslation($value, 'language', $locale)
getScriptTranslation($value, $locale) | getTranslation($value, 'script', $locale)
getCountryTranslation($value, $locale) | getTranslation($value, 'country', $locale)
getTerritoryTranslation($value, $locale) | getTranslation($value, 'territory', $locale)

Zend_View_Helper_Navigation

Prior to the 1.9 release, the menu helper (Zend_View_Helper_Navigation_Menu) did not render sub menus correctly. When onlyActiveBranch was TRUE and the option renderParents FALSE, nothing would be rendered if the deepest active page was at a depth lower than the minDepth option.

In simpler words; if minDepth was set to '1' and the active page was at one of the first level pages, nothing would be rendered, as the following example shows.

Consider the following container setup:

  1. <?php
  2. $container = new Zend_Navigation(array(
  3.     array(
  4.         'label' => 'Home',
  5.         'uri'   => '#'
  6.     ),
  7.     array(
  8.         'label'  => 'Products',
  9.         'uri'    => '#',
  10.         'active' => true,
  11.         'pages'  => array(
  12.             array(
  13.                 'label' => 'Server',
  14.                 'uri'   => '#'
  15.             ),
  16.             array(
  17.                 'label' => 'Studio',
  18.                 'uri'   => '#'
  19.             )
  20.         )
  21.     ),
  22.     array(
  23.         'label' => 'Solutions',
  24.         'uri'   => '#'
  25.     )
  26. ));

The following code is used in a view script:

  1. <?php echo $this->navigation()->menu()->renderMenu($container, array(
  2.     'minDepth'         => 1,
  3.     'onlyActiveBranch' => true,
  4.     'renderParents'    => false
  5. )); ?>

Before release 1.9, the code snippet above would output nothing.

Since release 1.9, the _renderDeepestMenu() method in Zend_View_Helper_Navigation_Menu will accept active pages at one level below minDepth, as long as the page has children.

The same code snippet will now output the following:

  1. <ul class="navigation">
  2.     <li>
  3.         <a href="#">Server</a>
  4.     </li>
  5.     <li>
  6.         <a href="#">Studio</a>
  7.     </li>
  8. </ul>

Security fixes as with 1.9.7

Additionally, users of the 1.9 series may be affected by other changes starting in version 1.9.7. These are all security fixes that also have potential backwards compatibility implications.

Zend_Dojo_View_Helper_Editor

A slight change was made in the 1.9 series to modify the default usage of the Editor dijit to use div tags instead of a textarea tag; the latter usage has » security implications, and usage of div tags is recommended by the Dojo project.

In order to still allow graceful degradation, a new degrade option was added to the view helper; this would allow developers to optionally use a textarea instead. However, this opens applications developed with that usage to XSS vectors. In 1.9.7, we have removed this option. Graceful degradation is still supported, however, via a noscript tag that embeds a textarea. This solution addressess all security concerns.

The takeaway is that if you were using the degrade flag, it will simply be ignored at this time.

Zend_Filter_HtmlEntities

In order to default to a more secure character encoding, Zend_Filter_HtmlEntities now defaults to UTF-8 instead of ISO-8859-1.

Additionally, because the actual mechanism is dealing with character encodings and not character sets, two new methods have been added, setEncoding() and getEncoding(). The previous methods setCharSet() and setCharSet() are now deprecated and proxy to the new methods. Finally, instead of using the protected members directly within the filter() method, these members are retrieved by their explicit accessors. If you were extending the filter in the past, please check your code and unit tests to ensure everything still continues to work.

Zend_Filter_StripTags

Zend_Filter_StripTags contains a flag, commentsAllowed, that, in previous versions, allowed you to optionally whitelist HTML comments in HTML text filtered by the class. However, this opens code enabling the flag to XSS attacks, particularly in Internet Explorer (which allows specifying conditional functionality via HTML comments). Starting in version 1.9.7 (and backported to versions 1.8.5 and 1.7.9), the commentsAllowed flag no longer has any meaning, and all HTML comments, including those containing other HTML tags or nested commments, will be stripped from the final output of the filter.

Zend Framework 1.10
Zend Framework Migration Notes
Zend Framework手册 中文版
Zend Framework 1.8
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Migration Notes
  • Zend Framework 1.10
  • Zend Framework 1.9
  • Zend Framework 1.8
  • Zend Framework 1.7
  • Zend Framework 1.6
  • Zend Framework 1.5
  • Zend Framework 1.0
  • Zend Framework 0.9
  • Zend Framework 0.8
  • Zend Framework 0.6


Zend Framework 1.8 - Zend Framework Manual

Zend Framework 1.9
Zend Framework Migration Notes
Zend Framework手册 中文版
Zend Framework 1.7

Zend Framework 1.8

When upgrading from a previous release to Zend Framework 1.8 or higher you should note the following migration notes.

Zend_Controller

Standard Route Changes

As translated segments were introduced into the new standard route, the '@' character is now a special character in the beginning of a route segment. To be able to use it in a static segment, you must escape it by prefixing it with second '@' character. The same rule now applies for the ':' character.

Zend_Locale

Default caching

As with Zend Framework 1.8 a default caching was added. The reason behind this change was, that most users had performance problems but did not add caching at all. As the I18n core is a bottleneck when no caching is used we decided to add a default caching when no cache has been set to Zend_Locale.

Sometimes it is still wanted to prevent caching at all even if this decreases performance. To do so you can simply disable caching by using the disableCache() method.

Example #1 Disabling default caching

  1. Zend_Locale::disableCache(true);
Zend Framework 1.9
Zend Framework Migration Notes
Zend Framework手册 中文版
Zend Framework 1.7
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Migration Notes
  • Zend Framework 1.10
  • Zend Framework 1.9
  • Zend Framework 1.8
  • Zend Framework 1.7
  • Zend Framework 1.6
  • Zend Framework 1.5
  • Zend Framework 1.0
  • Zend Framework 0.9
  • Zend Framework 0.8
  • Zend Framework 0.6


Zend Framework 1.7 - Zend Framework Manual

Zend Framework 1.8
Zend Framework Migration Notes
Zend Framework手册 中文版
Zend Framework 1.6

Zend Framework 1.7

When upgrading from a previous release to Zend Framework 1.7 or higher you should note the following migration notes.

Zend_Controller

Dispatcher Interface Changes

Users brought to our attention the fact that Zend_Controller_Action_Helper_ViewRenderer were using a method of the dispatcher abstract class that was not in the dispatcher interface. We have now added the following method to ensure that custom dispatchers will continue to work with the shipped implementations:

  • formatModuleName(): should be used to take a raw controller name, such as one that would be packaged inside a request object, and reformat it to a proper class name that a class extending Zend_Controller_Action would use

Zend_File_Transfer

Changes when using filters and validators

As noted by users, the validators from Zend_File_Transfer do not work in conjunction with Zend_Config due to the fact that they have not used named arrays.

Therefor, all filters and validators for Zend_File_Transfer have been reworked. While the old signatures continue to work, they have been marked as deprecated, and will emit a PHP notice asking you to fix them.

The following list shows you the changes you will have to do for proper usage of the parameters.

Filter: Rename

  • Old method API: Zend_Filter_File_Rename($oldfile, $newfile, $overwrite)

  • New method API: Zend_Filter_File_Rename($options) where $options accepts the following array keys: source equals to $oldfile, target equals to $newfile, overwrite equals to $overwrite.

Example #1 Changes for the rename filter from 1.6 to 1.7

  1. // Example for 1.6
  2. $upload = new Zend_File_Transfer_Adapter_Http();
  3. $upload->addFilter('Rename',
  4.                    array('/path/to/oldfile', '/path/to/newfile', true));
  5.
  6. // Same example for 1.7
  7. $upload = new Zend_File_Transfer_Adapter_Http();
  8. $upload->addFilter('Rename',
  9.                    array('source' => '/path/to/oldfile',
  10.                          'target' => '/path/to/newfile',
  11.                          'overwrite' => true));

Validator: Count

  • Old method API: Zend_Validate_File_Count($min, $max)

  • New method API: Zend_Validate_File_Count($options) where $options accepts the following array keys: min equals to $min, max equals to $max.

Example #2 Changes for the count validator from 1.6 to 1.7

  1. // Example for 1.6
  2. $upload = new Zend_File_Transfer_Adapter_Http();
  3. $upload->addValidator('Count',
  4.                       array(2, 3));
  5.
  6. // Same example for 1.7
  7. $upload = new Zend_File_Transfer_Adapter_Http();
  8. $upload->addValidator('Count',
  9.                       false,
  10.                       array('min' => 2,
  11.                             'max' => 3));

Validator:Extension

  • Old method API: Zend_Validate_File_Extension($extension, $case)

  • New method API: Zend_Validate_File_Extension($options) where $options accepts the following array keys: * equals to $extension and can have any other key, case equals to $case.

Example #3 Changes for the extension validator from 1.6 to 1.7

  1. // Example for 1.6
  2. $upload = new Zend_File_Transfer_Adapter_Http();
  3. $upload->addValidator('Extension',
  4.                       array('jpg,gif,bmp', true));
  5.
  6. // Same example for 1.7
  7. $upload = new Zend_File_Transfer_Adapter_Http();
  8. $upload->addValidator('Extension',
  9.                       false,
  10.                       array('extension1' => 'jpg,gif,bmp',
  11.                             'case' => true));

Validator: FilesSize

  • Old method API: Zend_Validate_File_FilesSize($min, $max, $bytestring)

  • New method API: Zend_Validate_File_FilesSize($options) where $options accepts the following array keys: min equals to $min, max equals to $max, bytestring equals to $bytestring.

Additionally, the useByteString() method signature has changed. It can only be used to test if the validator is expecting to use byte strings in generated messages. To set the value of the flag, use the setUseByteString() method.

Example #4 Changes for the filessize validator from 1.6 to 1.7

  1. // Example for 1.6
  2. $upload = new Zend_File_Transfer_Adapter_Http();
  3. $upload->addValidator('FilesSize',
  4.                    array(100, 10000, true));
  5.
  6. // Same example for 1.7
  7. $upload = new Zend_File_Transfer_Adapter_Http();
  8. $upload->addValidator('FilesSize',
  9.                       false,
  10.                       array('min' => 100,
  11.                             'max' => 10000,
  12.                             'bytestring' => true));
  13.
  14. // Example for 1.6
  15. $upload->useByteString(true); // set flag
  16.
  17. // Same example for 1.7
  18. $upload->setUseByteSting(true); // set flag

Validator: Hash

  • Old method API: Zend_Validate_File_Hash($hash, $algorithm)

  • New method API: Zend_Validate_File_Hash($options) where $options accepts the following array keys: * equals to $hash and can have any other key, algorithm equals to $algorithm.

Example #5 Changes for the hash validator from 1.6 to 1.7

  1. // Example for 1.6
  2. $upload = new Zend_File_Transfer_Adapter_Http();
  3. $upload->addValidator('Hash',
  4.                    array('12345', 'md5'));
  5.
  6. // Same example for 1.7
  7. $upload = new Zend_File_Transfer_Adapter_Http();
  8. $upload->addValidator('Hash',
  9.                       false,
  10.                       array('hash1' => '12345',
  11.                             'algorithm' => 'md5'));

Validator: ImageSize

  • Old method API: Zend_Validate_File_ImageSize($minwidth, $minheight, $maxwidth, $maxheight)

  • New method API: Zend_Validate_File_FilesSize($options) where $options accepts the following array keys: minwidth equals to $minwidth, maxwidth equals to $maxwidth, minheight equals to $minheight, maxheight equals to $maxheight.

Example #6 Changes for the imagesize validator from 1.6 to 1.7

  1. // Example for 1.6
  2. $upload = new Zend_File_Transfer_Adapter_Http();
  3. $upload->addValidator('ImageSize',
  4.                       array(10, 10, 100, 100));
  5.
  6. // Same example for 1.7
  7. $upload = new Zend_File_Transfer_Adapter_Http();
  8. $upload->addValidator('ImageSize',
  9.                       false,
  10.                       array('minwidth' => 10,
  11.                             'minheight' => 10,
  12.                             'maxwidth' => 100,
  13.                             'maxheight' => 100));

Validator: Size

  • Old method API: Zend_Validate_File_Size($min, $max, $bytestring)

  • New method API: Zend_Validate_File_Size($options) where $options accepts the following array keys: min equals to $min, max equals to $max, bytestring equals to $bytestring.

Example #7 Changes for the size validator from 1.6 to 1.7

  1. // Example for 1.6
  2. $upload = new Zend_File_Transfer_Adapter_Http();
  3. $upload->addValidator('Size',
  4.                       array(100, 10000, true));
  5.
  6. // Same example for 1.7
  7. $upload = new Zend_File_Transfer_Adapter_Http();
  8. $upload->addValidator('Size',
  9.                       false,
  10.                       array('min' => 100,
  11.                             'max' => 10000,
  12.                             'bytestring' => true));

Zend_Locale

Changes when using isLocale()

According to the coding standards isLocale() had to be changed to return a boolean. In previous releases a string was returned on success. For release 1.7 a compatibility mode has been added which allows to use the old behaviour of a returned string, but it triggers a user warning to mention you to change to the new behaviour. The rerouting which the old behaviour of isLocale() could have done is no longer neccessary as all I18n will now process a rerouting themself.

To migrate your scripts to the new API, simply use the method as shown below.

Example #8 How to change isLocale() from 1.6 to 1.7

  1. // Example for 1.6
  2. if ($locale = Zend_Locale::isLocale($locale)) {
  3.     // do something
  4. }
  5.
  6. // Same example for 1.7
  7.
  8. // You should change the compatiblity mode to prevent user warnings
  9. // But you can do this in your bootstrap
  10. Zend_Locale::$compatibilityMode = false;
  11.
  12. if (Zend_Locale::isLocale($locale)) {
  13. }

Note that you can use the second parameter to see if the locale is correct without processing a rerouting.

  1. // Example for 1.6
  2. if ($locale = Zend_Locale::isLocale($locale, false)) {
  3.     // do something
  4. }
  5.
  6. // Same example for 1.7
  7.
  8. // You should change the compatiblity mode to prevent user warnings
  9. // But you can do this in your bootstrap
  10. Zend_Locale::$compatibilityMode = false;
  11.
  12. if (Zend_Locale::isLocale($locale, false)) {
  13.     if (Zend_Locale::isLocale($locale, true)) {
  14.         // no locale at all
  15.     }
  16.
  17.     // original string is no locale but can be rerouted
  18. }

Changes when using getDefault()

The meaning of the getDefault() method has been change due to the fact that we integrated a framework locale which can be set with setDefault(). It does no longer return the locale chain but only the set framework locale.

To migrate your scripts to the new API, simply use the method as shown below.

Example #9 How to change getDefault() from 1.6 to 1.7

  1. // Example for 1.6
  2. $locales = $locale->getDefault(Zend_Locale::BROWSER);
  3.
  4. // Same example for 1.7
  5.
  6. // You should change the compatiblity mode to prevent user warnings
  7. // But you can do this in your bootstrap
  8. Zend_Locale::$compatibilityMode = false;
  9.
  10. $locale = Zend_Locale::getOrder(Zend_Locale::BROWSER);

Note that the second parameter of the old getDefault() implementation is not available anymore, but the returned values are the same.

Note: Per default the old behaviour is still active, but throws a user warning. When you have changed your code to the new behaviour you should also change the compatibility mode to FALSE so that no warning is thrown anymore.

Zend_Translate

Setting languages

When using automatic detection of languages, or setting languages manually to Zend_Translate you may have mentioned that from time to time a notice is thrown about not added or empty translations. In some previous release also an exception was raised in some cases.

The reason is, that when a user requests a non existing language, you have no simple way to detect what's going wrong. So we added those notices which show up in your log and tell you that the user requested a language which you do not support. Note that the code, even when we trigger such an notice, keeps working without problems.

But when you use a own error or exception handler, like xdebug, you will get all notices returned, even if this was not your intention. This is due to the fact that these handlers override all settings from within PHP.

To get rid of these notices you can simply set the new option 'disableNotices' to TRUE. It defaults to FALSE.

Example #10 Setting languages without getting notices

Let's assume that we have 'en' available and our user requests 'fr' which is not in our portfolio of translated languages.

  1. $language = new Zend_Translate('gettext',
  2.                                '/path/to/translations',
  3.                                'auto');

In this case we will get an notice about a not available language 'fr'. Simply add the option and the notices will be disabled.

  1. $language = new Zend_Translate('gettext',
  2.                                '/path/to/translations',
  3.                                'auto',
  4.                                array('disableNotices' => true));

Zend_View

Note: The API changes within Zend_View are only notable for you when you are upgrading to release 1.7.5 or higher.

Prior to the 1.7.5 release, the Zend Framework team was notified of a potential Local File Inclusion (LFI) vulnerability in the Zend_View::render() method. Prior to 1.7.5, the method allowed, by default, the ability to specify view scripts that included parent directory notation (e.g., "../" or "..\"). This opens the possibility for an LFI attack if unfiltered user input is passed to the render() method:

  1. // Where $_GET['foobar'] = '../../../../etc/passwd'
  2. echo $view->render($_GET['foobar']); // LFI inclusion

Zend_View now by default raises an exception when such a view script is requested.

Disabling LFI protection for the render() method

Since a number of developers reported that they were using such notation within their applications that was not the result of user input, a special flag was created to allow disabling the default protection. You have two methods for doing so: by passing the 'lfiProtectionOn' key to the constructor options, or by explicitly calling the setLfiProtection() method.

  1. // Disabling via constructor
  2. $view = new Zend_View(array('lfiProtectionOn' => false));
  3.
  4. // Disabling via exlicit method call:
  5. $view = new Zend_View();
  6. $view->setLfiProtection(false);
Zend Framework 1.8
Zend Framework Migration Notes
Zend Framework手册 中文版
Zend Framework 1.6
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Migration Notes
  • Zend Framework 1.10
  • Zend Framework 1.9
  • Zend Framework 1.8
  • Zend Framework 1.7
  • Zend Framework 1.6
  • Zend Framework 1.5
  • Zend Framework 1.0
  • Zend Framework 0.9
  • Zend Framework 0.8
  • Zend Framework 0.6


Zend Framework 1.6 - Zend Framework Manual

Zend Framework 1.7
Zend Framework Migration Notes
Zend Framework手册 中文版
Zend Framework 1.5

Zend Framework 1.6

When upgrading from a previous release to Zend Framework 1.6 or higher you should note the following migration notes.

Zend_Controller

Dispatcher Interface Changes

Users brought to our attention the fact that Zend_Controller_Front and Zend_Controller_Router_Route_Module were each using methods of the dispatcher that were not in the dispatcher interface. We have now added the following three methods to ensure that custom dispatchers will continue to work with the shipped implementations:

  • getDefaultModule(): should return the name of the default module.

  • getDefaultControllerName(): should return the name of the default controller.

  • getDefaultAction(): should return the name of the default action.

Zend_File_Transfer

Changes when using validators

As noted by users, the validators from Zend_File_Transfer do not work the same way like the default ones from Zend_Form. Zend_Form allows the usage of a $breakChainOnFailure parameter which breaks the validation for all further validators when an validation error has occurred.

So we added this parameter also to all existing validators from Zend_File_Transfer.

  • Old method API: addValidator($validator, $options, $files).

  • New method API: addValidator($validator, $breakChainOnFailure, $options, $files).

To migrate your scripts to the new API, simply add a FALSE after defining the wished validator.

Example #1 How to change your file validators from 1.6.1 to 1.6.2

  1. // Example for 1.6.1
  2. $upload = new Zend_File_Transfer_Adapter_Http();
  3. $upload->addValidator('FilesSize', array('1B', '100kB'));
  4.
  5. // Same example for 1.6.2 and newer
  6. // Note the added boolean false
  7. $upload = new Zend_File_Transfer_Adapter_Http();
  8. $upload->addValidator('FilesSize', false, array('1B', '100kB'));
Zend Framework 1.7
Zend Framework Migration Notes
Zend Framework手册 中文版
Zend Framework 1.5
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Migration Notes
  • Zend Framework 1.10
  • Zend Framework 1.9
  • Zend Framework 1.8
  • Zend Framework 1.7
  • Zend Framework 1.6
  • Zend Framework 1.5
  • Zend Framework 1.0
  • Zend Framework 0.9
  • Zend Framework 0.8
  • Zend Framework 0.6


Zend Framework 1.5 - Zend Framework Manual

Zend Framework 1.6
Zend Framework Migration Notes
Zend Framework手册 中文版
Zend Framework 1.0

Zend Framework 1.5

When upgrading from a previous release to Zend Framework 1.5 or higher you should note the following migration notes.

Zend_Controller

Though most basic functionality remains the same, and all documented functionality remains the same, there is one particular undocumented "feature" that has changed.

When writing URLs, the documented way to write camelCased action names is to use a word separator; these are '.' or '-' by default, but may be configured in the dispatcher. The dispatcher internally lowercases the action name, and uses these word separators to re-assemble the action method using camelCasing. However, because PHP functions are not case sensitive, you could still write URLs using camelCasing, and the dispatcher would resolve these to the same location. For example, 'camel-cased' would become 'camelCasedAction' by the dispatcher, whereas 'camelCased' would become 'camelcasedAction'; however, due to the case insensitivity of PHP, both will execute the same method.

This causes issues with the ViewRenderer when resolving view scripts. The canonical, documented way is that all word separators are converted to dashes, and the words lowercased. This creates a semantic tie between the actions and view scripts, and the normalization ensures that the scripts can be found. However, if the action 'camelCased' is called and actually resolves, the word separator is no longer present, and the ViewRenderer attempts to resolve to a different location -- camelcased.phtml instead of camel-cased.phtml.

Some developers relied on this "feature", which was never intended. Several changes in the 1.5.0 tree, however, made it so that the ViewRenderer no longer resolves these paths; the semantic tie is now enforced. First among these, the dispatcher now enforces case sensitivity in action names. What this means is that referring to your actions on the url using camelCasing will no longer resolve to the same method as using word separators (i.e., 'camel-casing'). This leads to the ViewRenderer now only honoring the word-separated actions when resolving view scripts.

If you find that you were relying on this "feature", you have several options:

  • Best option: rename your view scripts. Pros: forward compatibility. Cons: if you have many view scripts that relied on the former, unintended behavior, you will have a lot of renaming to do.

  • Second best option: The ViewRenderer now delegates view script resolution to Zend_Filter_Inflector; you can modify the rules of the inflector to no longer separate the words of an action with a dash:

    1. $viewRenderer =
    2.     Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
    3. $inflector = $viewRenderer->getInflector();
    4. $inflector->setFilterRule(':action', array(
    5.     new Zend_Filter_PregReplace(
    6.         '#[^a-z0-9' . preg_quote(DIRECTORY_SEPARATOR, '#') . ']+#i',
    7.         ''
    8.     ),
    9.     'StringToLower'
    10. ));

    The above code will modify the inflector to no longer separate the words with dash; you may also want to remove the 'StringToLower' filter if you do want the actual view script names camelCased as well.

    If renaming your view scripts would be too tedious or time consuming, this is your best option until you can find the time to do so.

  • Least desirable option: You can force the dispatcher to dispatch camelCased action names with a new front controller flag, useCaseSensitiveActions:

    1. $front->setParam('useCaseSensitiveActions', true);

    This will allow you to use camelCasing on the url and still have it resolve to the same action as when you use word separators. However, this will mean that the original issues will cascade on through; you will likely need to use the second option above in addition to this for things to work at all reliably.

    Note, also, that usage of this flag will raise a notice that this usage is deprecated.

Zend Framework 1.6
Zend Framework Migration Notes
Zend Framework手册 中文版
Zend Framework 1.0
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Migration Notes
  • Zend Framework 1.10
  • Zend Framework 1.9
  • Zend Framework 1.8
  • Zend Framework 1.7
  • Zend Framework 1.6
  • Zend Framework 1.5
  • Zend Framework 1.0
  • Zend Framework 0.9
  • Zend Framework 0.8
  • Zend Framework 0.6


Zend Framework 1.0 - Zend Framework Manual

Zend Framework 1.5
Zend Framework Migration Notes
Zend Framework手册 中文版
Zend Framework 0.9

Zend Framework 1.0

When upgrading from a previous release to Zend Framework 1.0 or higher you should note the following migration notes.

Zend_Controller

The principal changes introduced in 1.0.0RC1 are the introduction of and default enabling of the ErrorHandler plugin and the ViewRenderer action helper. Please read the documentation to each thoroughly to see how they work and what effect they may have on your applications.

The ErrorHandler plugin runs during postDispatch() checking for exceptions, and forwarding to a specified error handler controller. You should include such a controller in your application. You may disable it by setting the front controller parameter noErrorHandler:

  1. $front->setParam('noErrorHandler', true);

The ViewRenderer action helper automates view injection into action controllers as well as autorendering of view scripts based on the current action. The primary issue you may encounter is if you have actions that do not render view scripts and neither forward or redirect, as the ViewRenderer will attempt to render a view script based on the action name.

There are several strategies you can take to update your code. In the short term, you can globally disable the ViewRenderer in your front controller bootstrap prior to dispatching:

  1. // Assuming $front is an instance of Zend_Controller_Front
  2. $front->setParam('noViewRenderer', true);

However, this is not a good long term strategy, as it means most likely you'll be writing more code.

When you're ready to start using the ViewRenderer functionality, there are several things to look for in your controller code. First, look at your action methods (the methods ending in 'Action'), and determine what each is doing. If none of the following is happening, you'll need to make changes:

  • Calls to $this->render();

  • Calls to $this->_forward();

  • Calls to $this->_redirect();

  • Calls to the Redirector action helper

The easiest change is to disable auto-rendering for that method:

  1. $this->_helper->viewRenderer->setNoRender();

If you find that none of your action methods are rendering, forwarding, or redirecting, you will likely want to put the above line in your preDispatch() or init() methods:

  1. public function preDispatch()
  2. {
  3.     // disable view script autorendering
  4.     $this->_helper->viewRenderer->setNoRender()
  5.     // .. do other things...
  6. }

If you are calling render(), and you're using the Conventional Modular directory structure, you'll want to change your code to make use of autorendering:

  • If you're rendering multiple view scripts in a single action, you don't need to change a thing.

  • If you're simply calling render() with no arguments, you can remove such lines.

  • If you're calling render() with arguments, and not doing any processing afterwards or rendering multiple view scripts, you can change these calls to read $this->_helper->viewRenderer();.

If you're not using the conventional modular directory structure, there are a variety of methods for setting the view base path and script path specifications so that you can make use of the ViewRenderer. Please read the ViewRenderer documentation for information on these methods.

If you're using a view object from the registry, or customizing your view object, or using a different view implementation, you'll want to inject the ViewRenderer with this object. This can be done easily at any time.

  • Prior to dispatching a front controller instance:

    1. // Assuming $view has already been defined
    2. $viewRenderer = new Zend_Controller_Action_Helper_ViewRenderer($view);
    3. Zend_Controller_Action_HelperBroker::addHelper($viewRenderer);

  • Any time during the bootstrap process:

    1. $viewRenderer =
    2.     Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
    3. $viewRenderer->setView($view);

There are many ways to modify the ViewRenderer, including setting a different view script to render, specifying replacements for all replaceable elements of a view script path (including the suffix), choosing a response named segment to utilize, and more. If you aren't using the conventional modular directory structure, you can even associate different path specifications with the ViewRenderer.

We encourage you to adapt your code to use the ErrorHandler and ViewRenderer as they are now core functionality.

Zend_Currency

Creating an object of Zend_Currency has become simpler. You no longer have to give a script or set it to NULL. The optional script parameter is now an option which can be set through the setFormat() method.

  1. $currency = new Zend_Currency($currency, $locale);

The setFormat() method takes now an array of options. These options are set permanently and override all previously set values. Also a new option 'precision' has been added. The following options have been refactored:

  • position: Replacement for the old 'rules' parameter.

  • script: Replacement for the old 'script' parameter.

  • format: Replacement for the old 'locale' parameter which does not set new currencies but only the number format.

  • display: Replacement for the old 'rules' parameter.

  • precision: New parameter.

  • name: Replacement for the ole 'rules' parameter. Sets the full currencies name.

  • currency: New parameter.

  • symbol: New parameter.

  1. $currency->setFormat(array $options);

The toCurrency() method no longer supports the optional 'script' and 'locale' parameters. Instead it takes an options array which can contain the same keys as for the setFormat() method.

  1. $currency->toCurrency($value, array $options);

The methods getSymbol(), getShortName(), getName(), getRegionList() and getCurrencyList() are no longer static and can be called from within the object. They return the set values of the object if no parameter has been set.

Zend Framework 1.5
Zend Framework Migration Notes
Zend Framework手册 中文版
Zend Framework 0.9
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Migration Notes
  • Zend Framework 1.10
  • Zend Framework 1.9
  • Zend Framework 1.8
  • Zend Framework 1.7
  • Zend Framework 1.6
  • Zend Framework 1.5
  • Zend Framework 1.0
  • Zend Framework 0.9
  • Zend Framework 0.8
  • Zend Framework 0.6


Zend Framework 0.9 - Zend Framework Manual

Zend Framework 1.0
Zend Framework Migration Notes
Zend Framework手册 中文版
Zend Framework 0.8

Zend Framework 0.9

When upgrading from a previous release to Zend Framework 0.9 or higher you should note the following migration notes.

Zend_Controller

0.9.3 introduces action helpers. As part of this change, the following methods have been removed as they are now encapsulated in the redirector action helper:

  • setRedirectCode(); use Zend_Controller_Action_Helper_Redirector::setCode().

  • setRedirectPrependBase(); use Zend_Controller_Action_Helper_Redirector::setPrependBase().

  • setRedirectExit(); use Zend_Controller_Action_Helper_Redirector::setExit().

Read the action helpers documentation for more information on how to retrieve and manipulate helper objects, and the redirector helper documentation for more information on setting redirect options (as well as alternate methods for redirecting).

Zend Framework 1.0
Zend Framework Migration Notes
Zend Framework手册 中文版
Zend Framework 0.8
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Migration Notes
  • Zend Framework 1.10
  • Zend Framework 1.9
  • Zend Framework 1.8
  • Zend Framework 1.7
  • Zend Framework 1.6
  • Zend Framework 1.5
  • Zend Framework 1.0
  • Zend Framework 0.9
  • Zend Framework 0.8
  • Zend Framework 0.6


Zend Framework 0.8 - Zend Framework Manual

Zend Framework 0.9
Zend Framework Migration Notes
Zend Framework手册 中文版
Zend Framework 0.6

Zend Framework 0.8

When upgrading from a previous release to Zend Framework 0.8 or higher you should note the following migration notes.

Zend_Controller

Per previous changes, the most basic usage of the MVC components remains the same:

  1. Zend_Controller_Front::run('/path/to/controllers');

However, the directory structure underwent an overhaul, several components were removed, and several others either renamed or added. Changes include:

  • Zend_Controller_Router was removed in favor of the rewrite router.

  • Zend_Controller_RewriteRouter was renamed to Zend_Controller_Router_Rewrite, and promoted to the standard router shipped with the framework; Zend_Controller_Front will use it by default if no other router is supplied.

  • A new route class for use with the rewrite router was introduced, Zend_Controller_Router_Route_Module; it covers the default route used by the MVC, and has support for controller modules.

  • Zend_Controller_Router_StaticRoute was renamed to Zend_Controller_Router_Route_Static.

  • Zend_Controller_Dispatcher was renamed Zend_Controller_Dispatcher_Standard.

  • Zend_Controller_Action::_forward()'s arguments have changed. The signature is now:

    1. final protected function _forward($action,
    2.                                   $controller = null,
    3.                                   $module = null,
    4.                                   array $params = null);

    $action is always required; if no controller is specified, an action in the current controller is assumed. $module is always ignored unless $controller is specified. Finally, any $params provided will be appended to the request object. If you do not require the controller or module, but still need to pass parameters, simply specify NULL for those values.

Zend Framework 0.9
Zend Framework Migration Notes
Zend Framework手册 中文版
Zend Framework 0.6
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Migration Notes
  • Zend Framework 1.10
  • Zend Framework 1.9
  • Zend Framework 1.8
  • Zend Framework 1.7
  • Zend Framework 1.6
  • Zend Framework 1.5
  • Zend Framework 1.0
  • Zend Framework 0.9
  • Zend Framework 0.8
  • Zend Framework 0.6


Zend Framework 0.6 - Zend Framework Manual

Zend Framework 0.8
Zend Framework Migration Notes
Zend Framework手册 中文版
Zend Framework 的 PHP 编码标准

Zend Framework 0.6

When upgrading from a previous release to Zend Framework 0.6 or higher you should note the following migration notes.

Zend_Controller

The most basic usage of the MVC components has not changed; you can still do each of the following:

  1. Zend_Controller_Front::run('/path/to/controllers');
  1. /* -- create a router -- */
  2. $router = new Zend_Controller_RewriteRouter();
  3. $router->addRoute('user',
  4.                   'user/:username',
  5.                   array('controller' => 'user', 'action' => 'info')
  6. );
  7.
  8. /* -- set it in a controller -- */
  9. $ctrl = Zend_Controller_Front::getInstance();
  10. $ctrl->setRouter($router);
  11.
  12. /* -- set controller directory and dispatch -- */
  13. $ctrl->setControllerDirectory('/path/to/controllers');
  14. $ctrl->dispatch();

We encourage use of the Response object to aggregate content and headers. This will allow for more flexible output format switching (for instance, JSON or XML instead of XHTML) in your applications. By default, dispatch() will render the response, sending both headers and rendering any content. You may also have the front controller return the response using returnResponse(), and then render the response using your own logic. A future version of the front controller may enforce use of the response object via output buffering.

There are many additional features that extend the existing API, and these are noted in the documentation.

The main changes you will need to be aware of will be found when subclassing the various components. Key amongst these are:

  • Zend_Controller_Front::dispatch() by default traps exceptions in the response object, and does not render them, in order to prevent sensitive system information from being rendered. You can override this in several ways:

    • Set throwExceptions() in the front controller:

      1. $front->throwExceptions(true);

    • Set renderExceptions() in the response object:

      1. $response->renderExceptions(true);
      2. $front->setResponse($response);
      3. $front->dispatch();
      4.
      5. // or:
      6. $front->returnResponse(true);
      7. $response = $front->dispatch();
      8. $response->renderExceptions(true);
      9. echo $response;

  • Zend_Controller_Dispatcher_Interface::dispatch() now accepts and returns a The Request Object instead of a dispatcher token.

  • Zend_Controller_Router_Interface::route() now accepts and returns a The Request Object instead of a dispatcher token.

  • Zend_Controller_Action changes include:

    • The constructor now accepts exactly three arguments, Zend_Controller_Request_Abstract $request, Zend_Controller_Response_Abstract $response, and Array $params (optional). Zend_Controller_Action::__construct() uses these to set the request, response, and invokeArgs properties of the object, and if overriding the constructor, you should do so as well. Better yet, use the init() method to do any instance configuration, as this method is called as the final action of the constructor.

    • run() is no longer defined as final, but is also no longer used by the front controller; its sole purpose is for using the class as a page controller. It now takes two optional arguments, a Zend_Controller_Request_Abstract $request and a Zend_Controller_Response_Abstract $response.

    • indexAction() no longer needs to be defined, but is encouraged as the default action. This allows using the RewriteRouter and action controllers to specify different default action methods.

    • __call() should be overridden to handle any undefined actions automatically.

    • _redirect() now takes an optional second argument, the HTTP code to return with the redirect, and an optional third argument, $prependBase, that can indicate that the base URL registered with the request object should be prepended to the url specified.

    • The $_action property is no longer set. This property was a Zend_Controller_Dispatcher_Token, which no longer exists in the current incarnation. The sole purpose of the token was to provide information about the requested controller, action, and URL parameters. This information is now available in the request object, and can be accessed as follows:

      1. // Retrieve the requested controller name
      2. // Access used to be via: $this->_action->getControllerName().
      3. // The example below uses getRequest(), though you may also directly
      4. // access the $_request property; using getRequest() is recommended as
      5. // a parent class may override access to the request object.
      6. $controller = $this->getRequest()->getControllerName();
      7.
      8. // Retrieve the requested action name
      9. // Access used to be via: $this->_action->getActionName().
      10. $action = $this->getRequest()->getActionName();
      11.
      12. // Retrieve the request parameters
      13. // This hasn't changed; the _getParams() and _getParam() methods simply
      14. // proxy to the request object now.
      15. $params = $this->_getParams();
      16. // request 'foo' parameter, using 'default' as default value if not found
      17. $foo = $this->_getParam('foo', 'default');

    • noRouteAction() has been removed. The appropriate way to handle non-existent action methods should you wish to route them to a default action is using __call():

      1. public function __call($method, $args)
      2. {
      3.     // If an unmatched 'Action' method was requested, pass on to the
      4.     // default action method:
      5.     if ('Action' == substr($method, -6)) {
      6.         return $this->defaultAction();
      7.     }
      8.
      9.     throw new Zend_Controller_Exception('Invalid method called');
      10. }

  •  Zend_Controller_RewriteRouter::setRewriteBase() has
been removed. Use  Zend_Controller_Front::setBaseUrl()
instead (or  Zend_Controller_Request_Http::setBaseUrl(),
if using that request class).

  • Zend_Controller_Plugin_Interface was replaced by Zend_Controller_Plugin_Abstract. All methods now accept and return a The Request Object instead of a dispatcher token.

Zend Framework 0.8
Zend Framework Migration Notes
Zend Framework手册 中文版
Zend Framework 的 PHP 编码标准
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Migration Notes
  • Zend Framework 1.10
  • Zend Framework 1.9
  • Zend Framework 1.8
  • Zend Framework 1.7
  • Zend Framework 1.6
  • Zend Framework 1.5
  • Zend Framework 1.0
  • Zend Framework 0.9
  • Zend Framework 0.8
  • Zend Framework 0.6


Zend Framework 的 PHP 编码标准 - Zend Framework Manual

Zend Framework 0.6
绪论

Zend Framework 的 PHP 编码标准

Table of Contents
  • 绪论
  • PHP File 文件格式
  • 命名约定
  • 编码风格
Zend Framework 0.6
Zend Framework手册 中文版
Zend Framework手册 中文版
绪论
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework简介
  • Learning Zend Framework
  • Zend Framework Reference
  • 系统需求
  • Zend Framework Migration Notes
  • Zend Framework 的 PHP 编码标准
  • Zend Framework Documentation Standard
  • Recommended Project Structure for Zend Framework MVC Applications
  • Zend Framework Performance Guide
  • 版权信息


绪论 - Zend Framework Manual

Zend Framework 的 PHP 编码标准
Zend Framework 的 PHP 编码标准
Zend Framework手册 中文版
PHP File 文件格式

绪论

适用范围

本文档提供的代码格式和文档的指南是给参与 Zend Framework 的个人和团队使用的，许多使用 Zend Framework 的开发者 也发现编码标准很有用，因为他们的代码风格和 Zend Framework 的代码保持一致。值得注意的是它要求切实努力来全面 详细说明编码标准。 注：有时候开发者认为在最详细的设计级别上标准的建立比标准所建议的更重要。Zend Framework 编码标准的指南 实践上很好地工作于 ZF 项目。你可以根据我们的 » license 中的条款来修改或使用它们。

ZF 编码标准的话题包括：

  • PHP File 文件格式

  • 命名约定

  • 编码风格

  • 注释文档

目标

编码标准对任何开发项目都很重要，特别是很多开发者在同一项目上工作。编码标准帮助确保代码的高质量、少 bug 和容易维护。

Zend Framework 的 PHP 编码标准
Zend Framework 的 PHP 编码标准
Zend Framework手册 中文版
PHP File 文件格式
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework 的 PHP 编码标准
  • 绪论
  • PHP File 文件格式
  • 命名约定
  • 编码风格


PHP File 文件格式 - Zend Framework Manual

绪论
Zend Framework 的 PHP 编码标准
Zend Framework手册 中文版
命名约定

PHP File 文件格式

常规

对于只包含有 PHP 代码的文件，结束标志（"?>"）是不允许存在的，PHP自身不需要（"?>"）, 这样做, 可以防止它的末尾的被意外地注入相应。

重要： 由 __HALT_COMPILER() 允许的任意的二进制代码的内容被 Zend Framework 中的 PHP 文件或由它们产生的文件禁止。 这个功能的使用只对一些安装脚本开放。

缩进

缩进由四个空格组成，禁止使用制表符 TAB 。

行的最大长度

一行 80 字符以内是比较合适，就是说，ZF 的开发者应当努力在可能的情况下保持每行代码少于 80 个字符，在有些情况下，长点也可以, 但最多为 120 个字符。

行结束标志

行结束标志遵循 Unix 文本文件的约定，行必需以单个换行符（LF）结束。换行符在文件中表示为 10，或16进制的 0x0A。

注：不要使用 苹果操作系统的回车（0x0D）或 Windows 电脑的回车换行组合如（0x0D,0x0A）。

绪论
Zend Framework 的 PHP 编码标准
Zend Framework手册 中文版
命名约定
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework 的 PHP 编码标准
  • 绪论
  • PHP File 文件格式
  • 命名约定
  • 编码风格


命名约定 - Zend Framework Manual

PHP File 文件格式
Zend Framework 的 PHP 编码标准
Zend Framework手册 中文版
编码风格

命名约定

类

Zend Framework 的类命名总是对应于其所属文件的目录结构的，ZF 标准库的根目录是 “Zend/”，ZF 特别（extras）库的根目录是 "ZendX/"，所有 Zend Framework 的类在其下按等级存放。

类名只允许有字母数字字符，在大部分情况下不鼓励使用数字。下划线只允许做路径分隔符；例如 Zend/Db/Table.php 文件里对应的类名称是 Zend_Db_Table。

如果类名包含多个单词，每个单词的第一个字母必须大写，连续的大写是不允许的，例如 “Zend_PDF” 是不允许的，而 "Zend_Pdf" 是可接受的。

这些约定为 Zend Framework 定义了一个伪命名空间机制。如果对开发者在他们的程序中切实可行，Zend Framework 将采用 PHP 命名空间特性（如果有的话）。

参见在标准和特别库中类名作为类名约定的例子。 重要： 依靠 ZF 库展开的代码，但又不是标准或特别库的一部分（例如程序代码或不是 Zend 发行的库），不要以 "Zend_" 或 "ZendX_" 开头。

文件名

对于其它文件，只有字母数字字符、下划线和短横线（"-"）可用，空格是绝对不允许的。

包含任何 PHP 代码的任何文件应当以 ".php" 扩展名结尾，众所周知的视图脚本除外。下面这些例子给出 Zend Framework 类可接受的文件名：

Zend/Db.php

Zend/Controller/Front.php

Zend/View/Helper/FormRadio.php
文件名必须遵循上述的对应类名的规则。

函数和方法

函数名只包含字母数字字符，下划线是不允许的。数字是允许的但大多数情况下不鼓励。

函数名总是以小写开头，当函数名包含多个单词，每个子的首字母必须大写，这就是所谓的 “驼峰” 格式。

我们一般鼓励使用冗长的名字，函数名应当长到足以说明函数的意图和行为。

这些是可接受的函数名的例子：

filterInput()

getElementById()

widgetFactory()

对于面向对象编程，实例或静态变量的访问器总是以 "get" 或 "set" 为前缀。在设计模式实现方面，如单态模式（singleton）或工厂模式（factory）， 方法的名字应当包含模式的名字，这样名字更能描述整个行为。

在对象中的方法，声明为 "private" 或 "protected" 的， 名称的首字符必须是一个单个的下划线，这是唯一的下划线在方法名字中的用法。声明为 "public" 的从不包含下划线。

全局函数 (如："floating functions") 允许但大多数情况下不鼓励，建议把这类函数封装到静态类里。

变量

变量只包含数字字母字符，大多数情况下不鼓励使用数字，下划线不接受。

声明为 "private" 或 "protected" 的实例变量名必须以一个单个下划线开头，这是唯一的下划线在程序中的用法，声明为 "public" 的不应当以下划线开头。

对函数名（见上面 3.3 节）一样，变量名总以小写字母开头并遵循“驼峰式”命名约定。

我们一般鼓励使用冗长的名字，这样容易理解代码，开发者知道把数据存到哪里。除非在小循环里，不鼓励使用简洁的名字如 "$i" 和 "$n" 。如果一个循环超过 20 行代码，索引的变量名必须有个具有描述意义的名字。

常量

常量包含数字字母字符和下划线，数字允许作为常量名。

常量名的所有字母必须大写。

常量中的单词必须以下划线分隔，例如可以这样 EMBED_SUPPRESS_EMBED_EXCEPTION 但不许这样 EMBED_SUPPRESSEMBEDEXCEPTION。

常量必须通过 "const" 定义为类的成员，强烈不鼓励使用 "define" 定义的全局常量。

PHP File 文件格式
Zend Framework 的 PHP 编码标准
Zend Framework手册 中文版
编码风格
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework 的 PHP 编码标准
  • 绪论
  • PHP File 文件格式
  • 命名约定
  • 编码风格


编码风格 - Zend Framework Manual

命名约定
Zend Framework 的 PHP 编码标准
Zend Framework手册 中文版
Zend Framework Documentation Standard

编码风格

PHP 代码划分（Demarcation）

PHP 代码总是用完整的标准的 PHP 标签定界：

<?php

?>

短标签（ ）是不允许的，只包含 PHP 代码的文件，不要结束标签 （参见 常规）。

字符串

字符串文字

当字符串是文字(不包含变量)，应当用单引号（ apostrophe ）来括起来：

$a = 'Example String';

包含单引号（'）的字符串文字

当文字字符串包含单引号（apostrophe ）就用双引号括起来，特别在 SQL 语句中有用：

$sql = "SELECT `id`, `name` from `people` WHERE `name`='Fred' OR `name`='Susan'";
在转义单引号时，上述语法是首选的，因为很容易阅读。

变量替换

变量替换有下面这些形式：

$greeting = "Hello $name, welcome back!";

$greeting = "Hello {$name}, welcome back!";

为保持一致，这个形式不允许：

$greeting = "Hello ${name}, welcome back!";

字符串连接

字符串必需用 "." 操作符连接，在它的前后加上空格以提高可读性：

$company = 'Zend' . ' ' . 'Technologies';

当用 "." 操作符连接字符串，鼓励把代码可以分成多个行，也是为提高可读性。在这些例子中，每个连续的行应当由 whitespace 来填补，例如 "." 和 "=" 对齐：

$sql = "SELECT `id`, `name` FROM `people` "
     . "WHERE `name` = 'Susan' "
     . "ORDER BY `name` ASC ";

数组

数字索引数组

索引不能为负数

建议数组索引从 0 开始。

当用 array 函数声明有索引的数组，在每个逗号的后面间隔空格以提高可读性：

$sampleArray = array(1, 2, 3, 'Zend', 'Studio');

可以用 "array" 声明多行有索引的数组，在每个连续行的开头要用空格填补对齐：

$sampleArray = array(1, 2, 3, 'Zend', 'Studio',
                     $a, $b, $c,
                     56.44, $d, 500);

关联数组

当用声明关联数组，array 我们鼓励把代码分成多行，在每个连续行的开头用空格填补来对齐键和值：

$sampleArray = array('firstKey'  => 'firstValue',
                     'secondKey' => 'secondValue');

类

类的声明

用 Zend Framework 的命名约定来命名类。

花括号应当从类名下一行开始(the "one true brace" form)。

每个类必须有一个符合 PHPDocumentor 标准的文档块。

类中所有代码必需用四个空格的缩进。

每个 PHP 文件中只有一个类。

放另外的代码到类里允许但不鼓励。在这样的文件中，用两行空格来分隔类和其它代码。

下面是个可接受的类的例子： // 459 9506 － 441 9658 下次从这里开始

/**
 * Documentation Block Here
 */
class SampleClass
{
    // 类的所有内容
    // 必需缩进四个空格
}

类成员变量

必须用Zend Framework的变量名约定来命名类成员变量。

变量的声明必须在类的顶部，在方法的上方声明。

不允许使用 var （因为 ZF 是基于 PHP 5 的 ），要用 private、 protected 或 public。 直接访问 public 变量是允许的但不鼓励，最好使用访问器 （set/get）。

函数和方法

函数和方法声明

必须用Zend Framework的函数名约定来命名函数。

在类中的函数必须用 private、 protected 或 public 声明它们的可见性。

象类一样，花括号从函数名的下一行开始(the "one true brace" form)。

函数名和括参数的圆括号中间没有空格。

强烈反对使用全局函数。

下面是可接受的在类中的函数声明的例子：

/**
 * Documentation Block Here
 */
class Foo
{
    /**
     * Documentation Block Here
     */
    public function bar()
    {
        // 函数的所有内容
        // 必需缩进四个空格
    }
}

注： 传址（Pass-by-reference）是在方法声明中允许的唯一的参数传递机制。

/**
 * Documentation Block Here
 */
class Foo
{
    /**
     * Documentation Block Here
     */
    public function bar(&$baz)
    {}
}

传址在调用时是严格禁止的。

返回值不能在圆括号中，这妨碍可读性而且如果将来方法被修改成传址方式，代码会有问题。

/**
 * Documentation Block Here
 */
class Foo
{
    /**
     * WRONG
     */
    public function bar()
    {
        return($this->bar);
    }

    /**
     * RIGHT
     */
    public function bar()
    {
        return $this->bar;
    }
}

函数和方法的用法

函数的参数应当用逗号和紧接着的空格分开，下面可接受的调用的例子中的函数带有三个参数：

threeArguments(1, 2, 3);

传址方式在调用的时候是严格禁止的，参见函数的声明一节如何正确使用函数的传址方式。

带有数组参数的函数，函数的调用可包括 "array" 提示并可以分成多行来提高可读性，同时，书写数组的标准仍然适用：

threeArguments(array(1, 2, 3), 2, 3);

threeArguments(array(1, 2, 3, 'Zend', 'Studio',
                     $a, $b, $c,
                     56.44, $d, 500), 2, 3);

控制语句

if/Else/Elseif

使用 if and elseif 的控制语句在条件语句的圆括号前后都必须有一个空格。

在圆括号里的条件语句，操作符必须用空格分开，鼓励使用多重圆括号以提高在复杂的条件中划分逻辑组合。

前花括号必须和条件语句在同一行，后花括号单独在最后一行，其中的内容用四个空格缩进。

if ($a != 2) {
    $a = 2;
}

对包括"elseif" 或 "else"的 "if" 语句，和 "if" 结构的格式类似， 下面的例子示例 "if" 语句， 包括 "elseif" 或 "else" 的格式约定：

if ($a != 2) {
    $a = 2;
} else {
    $a = 7;
}

if ($a != 2) {
    $a = 2;
} elseif ($a == 3) {
    $a = 4;
} else {
    $a = 7;
}
在有些情况下， PHP 允许这些语句不用花括号，但在(ZF) 代码标准里，它们（"if"、 "elseif" 或 "else" 语句）必须使用花括号。

"elseif" 是允许的但强烈不鼓励，我们支持 "else if" 组合。

Switch

在 "switch" 结构里的控制语句在条件语句的圆括号前后必须都有一个单个的空格。

"switch" 里的代码必须有四个空格缩进，在"case"里的代码再缩进四个空格。

switch ($numPeople) {
    case 1:
        break;

    case 2:
        break;

    default:
        break;
}

switch 语句应当有 default。

注： 有时候，在 falls through 到下个 case 的 case 语句中不写 break or return 很有用。 为了区别于 bug，任何 case 语句中，所有不写 break or return 的地方应当有一个 "// break intentionally omitted" 这样的注释来表明 break 是故意忽略的。

注释文档

格式

所有文档块 ("docblocks") 必须和 phpDocumentor 格式兼容，phpDocumentor 格式的描述超出了本文档的范围，关于它的详情，参考：» http://phpdoc.org/。

所有类文件必须在文件的顶部包含文件级 （"file-level"）的 docblock ，在每个类的顶部放置一个 "class-level" 的 docblock。下面是一些例子：

文件

每个包含 PHP 代码的文件必须至少在文件顶部的 docblock 包含这些 phpDocumentor 标签：

/**
 * 文件的简短描述
 *
 * 文件的详细描述（如果有的话）... ...
 *
 * LICENSE: 一些 license 信息
 *
 * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/3_0.txt   BSD License
 * @version    $Id:$
 * @link       http://framework.zend.com/package/PackageName
 * @since      File available since Release 1.5.0
*/

类

每个类必须至少包含这些 phpDocumentor 标签：

/**
 * 类的简述
 *
 * 类的详细描述 （如果有的话）... ...
 *
 * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
 * @license    http://framework.zend.com/license/   BSD License
 * @version    Release: @package_version@
 * @link       http://framework.zend.com/package/PackageName
 * @since      Class available since Release 1.5.0
 * @deprecated Class deprecated in Release 2.0.0
 */

函数

每个函数，包括对象方法，必须有最少包含下列内容的文档块（docblock）：

  • 函数的描述

  • 所有参数

  • 所有可能的返回值

因为访问级已经通过 "public"、 "private" 或 "protected" 声明， 不需要使用 "@access"。

如果函数/方法抛出一个异常，使用 @throws 于所有已知的异常类：

@throws exceptionclass [description]

命名约定
Zend Framework 的 PHP 编码标准
Zend Framework手册 中文版
Zend Framework Documentation Standard
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework 的 PHP 编码标准
  • 绪论
  • PHP File 文件格式
  • 命名约定
  • 编码风格


Zend Framework Documentation Standard - Zend Framework Manual

编码风格
Overview

Zend Framework Documentation Standard

Table of Contents
  • Overview
  • Documentation File Formatting
  • Recommendations
编码风格
Zend Framework手册 中文版
Zend Framework手册 中文版
Overview
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework简介
  • Learning Zend Framework
  • Zend Framework Reference
  • 系统需求
  • Zend Framework Migration Notes
  • Zend Framework 的 PHP 编码标准
  • Zend Framework Documentation Standard
  • Recommended Project Structure for Zend Framework MVC Applications
  • Zend Framework Performance Guide
  • 版权信息


Overview - Zend Framework Manual

Zend Framework Documentation Standard
Zend Framework Documentation Standard
Zend Framework手册 中文版
Documentation File Formatting

Overview

Scope

This document provides guidelines for creation of the end-user documentation found within Zend Framework. It is intended as a guide to Zend Framework contributors, who must write documentation as part of component contributions, as well as to documentation translators. The standards contained herein are intended to ease translation of documentation, minimize visual and stylistic differences between different documentation files, and make finding changes in documentation easier with diff tools.

You may adopt and/or modify these standards in accordance with the terms of our » license.

Topics covered in Zend Framework's documentation standards include documentation file formatting and recommendations for documentation quality.

Zend Framework Documentation Standard
Zend Framework Documentation Standard
Zend Framework手册 中文版
Documentation File Formatting
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Documentation Standard
  • Overview
  • Documentation File Formatting
  • Recommendations


Documentation File Formatting - Zend Framework Manual

Overview
Zend Framework Documentation Standard
Zend Framework手册 中文版
Recommendations

Documentation File Formatting

XML Tags

Each manual file must include the following XML declarations at the top of the file:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- Reviewed: no -->

XML files from translated languages must also include a revision tag containing the revision of the corresponding English-language file the translation was based on.

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- EN-Revision: 14978 -->
  3. <!-- Reviewed: no -->

Maximum Line Length

The maximum line length, including tags, attributes, and indentation, is not to exceed 100 characters. There is only one exception to this rule: attribute and value pairs are allowed to exceed the 100 chars as they are not allowed to be separated.

Indentation

Indentation should consist of 4 spaces. Tabs are not allowed.

Tags which are at the same level must have the same indentation.

  1. <sect1>
  2. </sect1>
  3.
  4. <sect1>
  5. </sect1>

Tags which are one level under the previous tag must be indented with 4 additional spaces.

  1. <sect1>
  2.     <sect2>
  3.     </sect2>
  4. </sect1>

Multiple block tags within the same line are not allowed; multiple inline tags are allowed, however.

  1. <!-- NOT ALLOWED: -->
  2. <sect1><sect2>
  3. </sect2></sect1>
  4.
  5. <!-- ALLOWED -->
  6. <para>
  7.     <classname>Zend_Magic</classname> does not exist. <classname>Zend_Acl</classname> does.
  8. </para>

Line Termination

Line termination follows the Unix text file convention. Lines must end with a single linefeed (LF) character. Linefeed characters are represented as ordinal 10, or hexadecimal 0x0A.

Note: Do not use carriage returns (CR) as is the convention in Apple OS's (0x0D) or the carriage return - linefeed combination (CRLF) as is standard for the Windows OS (0x0D, 0x0A).

Empty tags

Empty tags are not allowed; all tags must contain text or child tags.

  1. <!-- NOT ALLOWED -->
  2. <para>
  3.     Some text. <link></link>
  4. </para>
  5.
  6. <para>
  7. </para>

Usage of whitespace within documents

Whitespace within tags

Opening block tags should have no whitespace immediately following them other than line breaks (and indentation on the following line).

  1. <!-- NOT ALLOWED -->
  2. <sect1>WHITESPACE
  3. </sect1>

Opening inline tags should have no whitespace immediately following them.

  1. <!-- NOT ALLOWED -->
  2. This is the class <classname> Zend_Class</classname>.
  3.
  4. <!-- OK -->
  5. This is the class <classname>Zend_Class</classname>.

Closing block tags may be preceded by whitespace equivalent to the current indentation level, but no more than that amount.

  1. <!-- NOT ALLOWED -->
  2.     <sect1>
  3.      </sect1>
  4.
  5. <!-- OK -->
  6.     <sect1>
  7.     </sect1>

Closing inline tags must not be preceded by any whitespace.

  1. <!-- NOT ALLOWED -->
  2. This is the class <classname>Zend_Class </classname>
  3.
  4. <!-- OK -->
  5. This is the class <classname>Zend_Class</classname>

Multiple line breaks

Multiple line breaks within or between tags are not allowed.

  1. <!-- NOT ALLOWED -->
  2. <para>
  3.     Some text...
  4.
  5.     ... and more text
  6. </para>
  7.
  8.
  9. <para>
  10.     Another paragraph.
  11. </para>
  12.
  13. <!-- OK -->
  14. <para>
  15.     Some text...
  16.     ... and more text
  17. </para>
  18.
  19. <para>
  20.     Another paragraph.
  21. </para>

Separation between tags

Tags at the same level must be separated by an empty line to improve readability.

  1. <!-- NOT ALLOWED -->
  2. <para>
  3.     Some text...
  4. </para>
  5. <para>
  6.     More text...
  7. </para>
  8.
  9. <!-- OK -->
  10. <para>
  11.     Some text...
  12. </para>
  13.
  14. <para>
  15.     More text...
  16. </para>

The first child tag should open directly below its parent, with no empty line between them; the last child tag should close directly before the closing tag of its parent.

  1. <!-- NOT ALLOWED -->
  2. <sect1>
  3.
  4.     <sect2>
  5.     </sect2>
  6.
  7.     <sect2>
  8.     </sect2>
  9.
  10.     <sect2>
  11.     </sect2>
  12.
  13. </sect1>
  14.
  15. <!-- OK -->
  16. <sect1>
  17.     <sect2>
  18.     </sect2>
  19.
  20.     <sect2>
  21.     </sect2>
  22.
  23.     <sect2>
  24.     </sect2>
  25. </sect1>

Program Listings

The opening <programlisting> tag must indicate the appropriate "language" attribute and be indented at the same level as its sibling blocks.

  1. <para>Sibling paragraph.</para>
  2.
  3. <programlisting language="php"><![CDATA[

CDATA should be used around all program listings.

<programlisting> sections must not add linebreaks or whitespace at the beginning or end of the section, as these are then represented in the final output.

  1. <!-- NOT ALLOWED -->
  2. <programlisting language="php"><![CDATA[
  3.
  4. $render = "xxx";
  5.
  6. ]]></programlisting>
  7.
  8. <!-- OK -->
  9. <programlisting language="php"><![CDATA[
  10. $render = "xxx";
  11. ]]></programlisting>

Ending CDATA and <programlisting> tags should be on the same line, without any indentation.

  1. <!-- NOT ALLOWED -->
  2.     <programlisting language="php"><![CDATA[
  3. $render = "xxx";
  4. ]]>
  5.     </programlisting>
  6.
  7. <!-- NOT ALLOWED -->
  8.     <programlisting language="php"><![CDATA[
  9. $render = "xxx";
  10.     ]]></programlisting>
  11.
  12. <!-- OK -->
  13.     <programlisting language="php"><![CDATA[
  14. $render = "xxx";
  15. ]]></programlisting>

The <programlisting> tag should contain the "language" attribute with a value appropriate to the contents of the program listing. Typical values include "css", "html", "ini", "javascript", "php", "text", and "xml".

  1. <!-- PHP -->
  2. <programlisting language="php"><![CDATA[
  3.
  4. <!-- Javascript -->
  5. <programlisting language="javascript"><![CDATA[
  6.
  7. <!-- XML -->
  8. <programlisting language="xml"><![CDATA[

For program listings containing only PHP code, PHP tags (e.g., "<?php", "?>") are not required, and should not be used. They simply clutter the narrative, and are implied by the use of the <programlisting> tag.

  1. <!-- NOT ALLOWED -->
  2. <programlisting language="php"<![CDATA[<?php
  3.     // ...
  4. ?>]]></programlisting>
  5.
  6. <programlisting language="php"<![CDATA[
  7. <?php
  8.     // ...
  9. ?>
  10. ]]></programlisting>

Line lengths within program listings should follow the coding standards recommendations.

Refrain from using  require_once(),
 require(),  include_once(), and
 include() calls within PHP listings.
They simply clutter the narrative, and are largely obviated when using an
autoloader. Use them only when they are essential to the example.

Note: Never use short tags
 Short tags (e.g., "<?", "<?=") should never be used within programlisting or the narrative of a document.

Notes on specific inline tags

classname

The tag <classname> must be used each time a class name is represented by itself; it should not be used when combined with a method name, variable name, or constant, and no other content is allowed within the tag.

  1. <para>
  2.     The class <classname>Zend_Class</classname>.
  3. </para>

varname

Variables must be wrapped in the <varname> tag. Variables must be written using the "$" sigil. No other content is allowed within this tag, unless a class name is used, which indicates a class variable.

  1. <para>
  2.     The variable <varname>$var</varname> and the class variable
  3.     <varname>Zend_Class::$var</varname>.
  4. </para>

methodname

Methods must be wrapped in the <methodname> tag. Methods must either include the full method signature or at the least a pair of closing parentheses (e.g., "()"). No other content is allowed within this tag, unless a class name is used, which indicates a class method.

  1. <para>
  2.     The method <methodname>foo()</methodname> and the class method
  3.     <methodname>Zend_Class::foo()</methodname>. A method with a full signature:
  4.     <methodname>foo($bar, $baz)</methodname>
  5. </para>

constant

Use the <constant> tag when denoting constants. Constants must be written in UPPERCASE. No other content is allowed within this tag, unless a class name is used, which indicates a class constant.

  1. <para>
  2.     The constant <constant>FOO</constant> and the class constant
  3.     <constant>Zend_Class::FOO</constant>.
  4. </para>

filename

Filenames and paths must be wrapped in the <filename> tag. No other content is allowed in this tag.

  1. <para>
  2.     The filename <filename>application/Bootstrap.php</filename>.
  3. </para>

command

Commands, shell scripts, and program calls must be wrapped in the <command> tag. If the command includes arguments, these should also be included within the tag.

  1. <para>
  2.     Execute <command>zf.sh create project</command>.
  3. </para>

code

Usage of the <code> tag is discouraged, in favor of the other inline tasks discussed previously.

Notes on specific block tags

title

The <title> tag is not allowed to hold other tags.

  1. <!-- NOT ALLOWED -->
  2. <title>Using <classname>Zend_Class</classname></title>
  3.
  4. <!-- OK -->
  5. <title>Using Zend_Class</title>
Overview
Zend Framework Documentation Standard
Zend Framework手册 中文版
Recommendations
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Documentation Standard
  • Overview
  • Documentation File Formatting
  • Recommendations


Recommendations - Zend Framework Manual

Documentation File Formatting
Zend Framework Documentation Standard
Zend Framework手册 中文版
Recommended Project Structure for Zend Framework MVC Applications

Recommendations

Use editors without autoformatting

For editing the documentation, typically you should not use formal XML editors. Such editors normally autoformat existing documents to fit their own standards and/or do not strictly follow the docbook standard. As examples, we have seen them erase the CDATA tags, change 4 space separation to tabs or 2 spaces, etc.

The style guidelines were written in large part to assist translators in recognizing the lines that have changed using normal diff tools. Autoformatting makes this process more difficult.

Use Images

Good images and diagrams can improve readability and comprehension. Use them whenever they will assist in these goals. Images should be placed in the documentation/manual/en/figures/ directory, and be named after the section identifier in which they occur.

Use Case Examples

Look for good use cases submitted by the community, especially those posted in proposal comments or on one of the mailing lists. Examples often illustrate usage far better than the narrative does.

When writing your examples for inclusion in the manual, follow all coding standards and documentation standards.

Avoid Replicating phpdoc Contents

The manual is intended to be a reference guide for end-user usage. Replicating the phpdoc documentation for internal-use components and classes is not wanted, and the narrative should be focussed on usage, not the internal workings. In any case, at this time, we would like the documentation teams to focus on translating the English manual, not the phpdoc comments.

Use Links

Link to other sections of the manual or to external sources instead of recreating documentation.

Linking to other sections of the manual may be done using either the <xref> tag (which will substitute the section title for the link text) or the <link> tag (to which you must provide link text).

  1. <para>
  2.     "Xref" links to a section: <xref
  3.         linkend="doc-standard.recommendations.links" />.
  4. </para>
  5.
  6. <para>
  7.     "Link" links to a section, using descriptive text: <link
  8.         linkend="doc-standard.recommendations.links">documentation on
  9.         links</link>.
  10. </para>

To link to an external resource, use <ulink>:

  1. <para>
  2.     The <ulink url="http://framework.zend.com/">Zend Framework site</ulink>.
  3. </para>
Documentation File Formatting
Zend Framework Documentation Standard
Zend Framework手册 中文版
Recommended Project Structure for Zend Framework MVC Applications
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Documentation Standard
  • Overview
  • Documentation File Formatting
  • Recommendations


Recommended Project Structure for Zend Framework MVC Applications - Zend Framework Manual

Recommendations
Overview

Recommended Project Structure for Zend Framework MVC Applications

Table of Contents
  • Overview
  • Recommended Project Directory Structure
  • Module Structure
  • Rewrite Configuration Guide
Recommendations
Zend Framework手册 中文版
Zend Framework手册 中文版
Overview
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework简介
  • Learning Zend Framework
  • Zend Framework Reference
  • 系统需求
  • Zend Framework Migration Notes
  • Zend Framework 的 PHP 编码标准
  • Zend Framework Documentation Standard
  • Recommended Project Structure for Zend Framework MVC Applications
  • Zend Framework Performance Guide
  • 版权信息


Overview - Zend Framework Manual

Recommended Project Structure for Zend Framework MVC Applications
Recommended Project Structure for Zend Framework MVC Applications
Zend Framework手册 中文版
Recommended Project Directory Structure

Overview

Many developers seek guidance on the best project structure for a Zend Framework project in a relatively flexible environment. A "flexible" environment is one in which the developer can manipulate their file systems and web server configurations as needed to achieve the most ideal project structure to run and secure their application. The default project structure will assume that the developer has such flexibility at their disposal.

The following directory structure is designed to be maximally extensible for complex projects, while providing a simple subset of folder and files for project with simpler requirements. This structure also works without alteration for both modular and non-modular Zend Framework applications. The .htaccess files require URL rewrite functionality in the web server as described in the Rewrite Configuration Guide, also included in this appendix.

It is not the intention that this project structure will support all possible Zend Framework project requirements. The default project profile used by Zend_Tool reflect this project structure, but applications with requirements not supported by this structure should use a custom project profile.

Recommended Project Structure for Zend Framework MVC Applications
Recommended Project Structure for Zend Framework MVC Applications
Zend Framework手册 中文版
Recommended Project Directory Structure
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Recommended Project Structure for Zend Framework MVC Applications
  • Overview
  • Recommended Project Directory Structure
  • Module Structure
  • Rewrite Configuration Guide


Recommended Project Directory Structure - Zend Framework Manual

Overview
Recommended Project Structure for Zend Framework MVC Applications
Zend Framework手册 中文版
Module Structure

Recommended Project Directory Structure

  1. <project name>/
  2.     application/
  3.         configs/
  4.             application.ini
  5.         controllers/
  6.             helpers/
  7.         forms/
  8.         layouts/
  9.             filters/
  10.             helpers/
  11.             scripts/
  12.         models/
  13.         modules/
  14.         services/
  15.         views/
  16.             filters/
  17.             helpers/
  18.             scripts/
  19.         Bootstrap.php
  20.     data/
  21.         cache/
  22.         indexes/
  23.         locales/
  24.         logs/
  25.         sessions/
  26.         uploads/
  27.     docs/
  28.     library/
  29.     public/
  30.         css/
  31.         images/
  32.         js/
  33.         .htaccess
  34.         index.php
  35.     scripts/
  36.         jobs/
  37.         build/
  38.     temp/
  39.     tests/

The following describes the use cases for each directory as listed.

  • application/: This directory contains your application. It will house the MVC system, as well as configurations, services used, and your bootstrap file.

    • configs/: The application-wide configuration directory.

    • controllers/, models/, and views/: These directories serve as the default controller, model or view directories. Having these three directories inside the application directory provides the best layout for starting a simple project as well as starting a modular project that has global controllers/models/views.

    • controllers/helpers/: These directories will contain action helpers. Action helpers will be namespaced either as "Controller_Helper_" for the default module or "<Module>_Controller_Helper" in other modules.

    • layouts/: This layout directory is for MVC-based layouts. Since Zend_Layout is capable of MVC- and non-MVC-based layouts, the location of this directory reflects that layouts are not on a 1-to-1 relationship with controllers and are independent of templates within views/.

    • modules/: Modules allow a developer to group a set of related controllers into a logically organized group. The structure under the modules directory would resemble the structure under the application directory.

    • services/: This directory is for your application specific web-service files that are provided by your application, or for implementing a » Service Layer for your models.

    • Bootstrap.php: This file is the entry point for your application, and should implement Zend_Application_Bootstrap_Bootstrapper. The purpose for this file is to bootstrap the application and make components available to the application by initializing them.

  • data/: This directory provides a place to store application data that is volatile and possibly temporary. The disturbance of data in this directory might cause the application to fail. Also, the information in this directory may or may not be committed to a subversion repository. Examples of things in this directory are session files, cache files, sqlite databases, logs and indexes.

  • docs/: This directory contains documentation, either generated or directly authored.

  • library/: This directory is for common libraries on which the application depends, and should be on the PHP include_path. Developers should place their application's library code under this directory in a unique namespace, following the guidelines established in the PHP manual's » Userland Naming Guide, as well as those established by Zend itself. This directory may also include Zend Framework itself; if so, you would house it in library/Zend/.

  • public/: This directory contains all public files for your application. index.php sets up and invokes Zend_Application, which in turn invokes the application/Bootstrap.php file, resulting in dispatching the front controller. The web root of your web server would typically be set to this directory.

  • scripts/: This directory contains maintenance and/or build scripts. Such scripts might include command line, cron, or phing build scripts that are not executed at runtime but are part of the correct functioning of the application.

  • temp/: The temp/ folder is set aside for transient application data. This information would not typically be committed to the applications svn repository. If data under the temp/ directory were deleted, the application should be able to continue running with a possible decrease in performance until data is once again restored or recached.

  • tests/: This directory contains application tests. These could be hand-written, PHPUnit tests, Selenium-RC based tests or based on some other testing framework. By default, library code can be tested by mimicing the directory structure of your library/ directory. Additionally, functional tests for your application could be written mimicing the application/ directory structure (including the application subdirectory).

Overview
Recommended Project Structure for Zend Framework MVC Applications
Zend Framework手册 中文版
Module Structure
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Recommended Project Structure for Zend Framework MVC Applications
  • Overview
  • Recommended Project Directory Structure
  • Module Structure
  • Rewrite Configuration Guide


Module Structure - Zend Framework Manual

Recommended Project Directory Structure
Recommended Project Structure for Zend Framework MVC Applications
Zend Framework手册 中文版
Rewrite Configuration Guide

Module Structure

The directory structure for modules should mimic that of the application/ directory in the recommended project structure:

  1. <modulename>
  2.     configs/
  3.         application.ini
  4.     controllers/
  5.         helpers/
  6.     forms/
  7.     layouts/
  8.         filters/
  9.         helpers/
  10.         scripts/
  11.     models/
  12.     services/
  13.     views/
  14.         filters/
  15.         helpers/
  16.         scripts/
  17.     Bootstrap.php

The purpose of these directories remains exactly the same as for the recommended project directory structure.

Recommended Project Directory Structure
Recommended Project Structure for Zend Framework MVC Applications
Zend Framework手册 中文版
Rewrite Configuration Guide
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Recommended Project Structure for Zend Framework MVC Applications
  • Overview
  • Recommended Project Directory Structure
  • Module Structure
  • Rewrite Configuration Guide


Rewrite Configuration Guide - Zend Framework Manual

Module Structure
Recommended Project Structure for Zend Framework MVC Applications
Zend Framework手册 中文版
Zend Framework Performance Guide

Rewrite Configuration Guide

URL rewriting is a common function of HTTP servers. However, the rules and configuration differ widely between them. Below are some common approaches across a variety of popular web servers available at the time of writing.

Apache HTTP Server

All examples that follow use mod_rewrite, an official module that comes bundled with Apache. To use it, mod_rewrite must either be included at compile time or enabled as a Dynamic Shared Object (DSO). Please consult the » Apache documentation for your version for more information.

Rewriting inside a VirtualHost

Here is a very basic virtual host definition. These rules direct all requests to index.php, except when a matching file is found under the document_root.

  1. <VirtualHost my.domain.com:80>
  2.     ServerName   my.domain.com
  3.     DocumentRoot /path/to/server/root/my.domain.com/public
  4.
  5.     RewriteEngine off
  6.
  7.     <Location />
  8.         RewriteEngine On
  9.         RewriteCond %{REQUEST_FILENAME} -s [OR]
  10.         RewriteCond %{REQUEST_FILENAME} -l [OR]
  11.         RewriteCond %{REQUEST_FILENAME} -d
  12.         RewriteRule ^.*$ - [NC,L]
  13.         RewriteRule ^.*$ /index.php [NC,L]
  14.     </Location>
  15. </VirtualHost>

Note the slash ("/") prefixing index.php; the rules for .htaccess differ in this regard.

Rewriting within a .htaccess file

Below is a sample .htaccess file that utilizes mod_rewrite. It is similar to the virtual host configuration, except that it specifies only the rewrite rules, and the leading slash is omitted from index.php.

  1. RewriteEngine On
  2. RewriteCond %{REQUEST_FILENAME} -s [OR]
  3. RewriteCond %{REQUEST_FILENAME} -l [OR]
  4. RewriteCond %{REQUEST_FILENAME} -d
  5. RewriteRule ^.*$ - [NC,L]
  6. RewriteRule ^.*$ index.php [NC,L]

There are many ways to configure mod_rewrite; if you would like more information, see Jayson Minard's » Blueprint for PHP Applications: Bootstrapping.

Microsoft Internet Information Server

As of version 7.0, IIS now ships with a standard rewrite engine. You may use the following configuration to create the appropriate rewrite rules.

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <configuration>
  3.     <system.webServer>
  4.         <rewrite>
  5.             <rules>
  6.                 <rule name="Imported Rule 1" stopProcessing="true">
  7.                     <match url="^.*$" />
  8.                     <conditions logicalGrouping="MatchAny">
  9.                         <add input="{REQUEST_FILENAME}"
  10.                              matchType="IsFile" pattern=""
  11.                              ignoreCase="false" />
  12.                         <add input="{REQUEST_FILENAME}"
  13.                              matchType="IsDirectory"
  14.                              pattern=""
  15.                              ignoreCase="false" />
  16.                     </conditions>
  17.                     <action type="None" />
  18.                 </rule>
  19.                 <rule name="Imported Rule 2" stopProcessing="true">
  20.                     <match url="^.*$" />
  21.                     <action type="Rewrite" url="index.php" />
  22.                 </rule>
  23.             </rules>
  24.         </rewrite>
  25.     </system.webServer>
  26. </configuration>
Module Structure
Recommended Project Structure for Zend Framework MVC Applications
Zend Framework手册 中文版
Zend Framework Performance Guide
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Recommended Project Structure for Zend Framework MVC Applications
  • Overview
  • Recommended Project Directory Structure
  • Module Structure
  • Rewrite Configuration Guide


Zend Framework Performance Guide - Zend Framework Manual

Rewrite Configuration Guide
介绍

Zend Framework Performance Guide

Table of Contents
  • 介绍
  • Class Loading
  • Zend_Db Performance
  • Internationalization (i18n) and Localization (l10n)
  • View Rendering
Rewrite Configuration Guide
Zend Framework手册 中文版
Zend Framework手册 中文版
介绍
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework简介
  • Learning Zend Framework
  • Zend Framework Reference
  • 系统需求
  • Zend Framework Migration Notes
  • Zend Framework 的 PHP 编码标准
  • Zend Framework Documentation Standard
  • Recommended Project Structure for Zend Framework MVC Applications
  • Zend Framework Performance Guide
  • 版权信息


介绍 - Zend Framework Manual

Zend Framework Performance Guide
Zend Framework Performance Guide
Zend Framework手册 中文版
Class Loading

介绍

编写这个附录的目的，是提供一些用于提升 Zend Framework 应用的性能的具体策略。本指南按照“问和答”的方式发布，并分解成相关领域。

Zend Framework Performance Guide
Zend Framework Performance Guide
Zend Framework手册 中文版
Class Loading
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Performance Guide
  • 介绍
  • Class Loading
  • Zend_Db Performance
  • Internationalization (i18n) and Localization (l10n)
  • View Rendering


Class Loading - Zend Framework Manual

介绍
Zend Framework Performance Guide
Zend Framework手册 中文版
Zend_Db Performance

Class Loading

Anyone who ever performs profiling of a Zend Framework application will immediately recognize that class loading is relatively expensive in Zend Framework. Between the sheer number of class files that need to be loaded for many components, to the use of plugins that do not have a 1:1 relationship between their class name and the file system, the various calls to include_once() and require_once() can be problematic. This chapter intends to provide some concrete solutions to these issues.

How can I optimize my include_path?

One trivial optimization you can do to increase the speed of class loading is to pay careful attention to your include_path. In particular, you should do four things: use absolute paths (or paths relative to absolute paths), reduce the number of include paths you define, have your Zend Framework include_path as early as possible, and only include the current directory path at the end of your include_path.

Use absolute paths

While this may seem a micro-optimization, the fact is that if you don't, you'll get very little benefit from PHP's realpath cache, and as a result, opcode caching will not perform nearly as you may expect.

There are two easy ways to ensure this. First, you can hardcode the paths in your php.ini, httpd.conf, or .htaccess. Second, you can use PHP's realpath() function when setting your include_path:

  1. $paths = array(
  2.     realpath(dirname(__FILE__) . '/../library'),
  3.     '.',
  4. );
  5. set_include_path(implode(PATH_SEPARATOR, $paths);

You can use relative paths -- so long as they are relative to an absolute path:

  1. define('APPLICATION_PATH', realpath(dirname(__FILE__)));
  2. $paths = array(
  3.     APPLICATION_PATH . '/../library'),
  4.     '.',
  5. );
  6. set_include_path(implode(PATH_SEPARATOR, $paths);

However, even so, it's typically a trivial task to simply pass the path to realpath().

Reduce the number of include paths you define

Include paths are scanned in the order in which they appear in the include_path. Obviously, this means that you'll get a result faster if the file is found on the first scan rather than the last. Thus, a rather obvious enhancement is to simply reduce the number of paths in your include_path to only what you need. Look through each include_path you've defined, and determine if you actually have any functionality in that path that is used in your application; if not, remove it.

Another optimization is to combine paths. For instance, Zend Framework follows PEAR naming conventions; thus, if you are using PEAR libraries (or libraries from another framework or component library that follows PEAR CS), try to put all of these libraries on the same include_path. This can often be achieved by something as simple as symlinking one or more libraries into a common directory.

Define your Zend Framework include_path as early as possible

Continuing from the previous suggestion, another obvious optimization is to define your Zend Framework include_path as early as possible in your include_path. In most cases, it should be the first path in the list. This ensures that files included from Zend Framework are found on the first scan.

Define the current directory last, or not at all

Most include_path examples show using the current directory, or '.'. This is convenient for ensuring that scripts in the same directory as the file requiring them can be loaded. However, these same examples typically show this path item as the first item in the include_path -- which means that the current directory tree is always scanned first. In most cases, with Zend Framework applications, this is not desired, and the path may be safely pushed to the last item in the list.

Example #1 Example: Optimized include_path

Let's put all of these suggestions together. Our assumption will be that you are using one or more PEAR libraries in conjunction with Zend Framework -- perhaps the PHPUnit and Archive_Tar libraries -- and that you occasionally need to include files relative to the current file.

First, we'll create a library directory in our project. Inside that directory, we'll symlink our Zend Framework's library/Zend directory, as well as the necessary directories from our PEAR installation:

  1. library
  2.     Archive/
  3.     PEAR/
  4.     PHPUnit/
  5.     Zend/

This allows us to add our own library code if necessary, while keeping shared libraries intact.

Next, we'll opt to create our include_path programmatically within our public/index.php file. This allows us to move our code around on the file system, without needing to edit the include_path every time.

We'll borrow ideas from each of the suggestions above: we'll use absolute paths, as determined using realpath(); we'll include Zend Framework's include path early; we've already consolidated include_paths; and we'll put the current directory as the last path. In fact, we're doing really well here -- we're going to end up with only two paths.

  1. $paths = array(
  2.     realpath(dirname(__FILE__) . '/../library'),
  3.     '.'
  4. );
  5. set_include_path(implode(PATH_SEPARATOR, $paths));

How can I eliminate unnecessary require_once statements?

Lazy loading is an optimization technique designed to push the expensive operation of loading a class file until the last possible moment -- i.e., when instantiating an object of that class, calling a static class method, or referencing a class constant or static property. PHP supports this via autoloading, which allows you to define one or more callbacks to execute in order to map a class name to a file.

However, most benefits you may reap from autoloading are negated if your library code is still performing require_once() calls -- which is precisely the case with Zend Framework. So, the question is: how can you eliminate those require_once() calls in order to maximize autoloader performance?

Strip require_once calls with find and sed

An easy way to strip require_once() calls is to use the UNIX utilities 'find' and 'sed' in conjunction to comment out each call. Try executing the following statements (where '%' indicates the shell prompt):

  1. % cd path/to/ZendFramework/library
  2. % find . -name '*.php' -not -wholename '*/Loader/Autoloader.php' \
  3.   -not -wholename '*/Application.php' -print0 | \
  4.   xargs -0 sed --regexp-extended --in-place 's/(require_once)/\/\/ \1/g'

This one-liner (broken into two lines for readability) iterates through each PHP file and tells it to replace each instance of 'require_once' with '// require_once', effectively commenting out each such statement. (It selectively keeps require_once() calls within Zend_Application and Zend_Loader_Autoloader, as these classes will fail without them.)

This command could be added to an automated build or release process trivially, helping boost performance in your production application. It should be noted, however, that if you use this technique, you must utilize autoloading; you can do that from your "public/index.php" file with the following code:

  1. require_once 'Zend/Loader/Autoloader.php';
  2. Zend_Loader_Autoloader::getInstance();

How can I speed up plugin loading?

Many components have plugins, which allow you to create your own classes to utilize with the component, as well as to override existing, standard plugins shipped with Zend Framework. This provides important flexibility to the framework, but at a price: plugin loading is a fairly expensive task.

The plugin loader allows you to register class prefix / path pairs, allowing you to specify class files in non-standard paths. Each prefix can have multiple paths associated with it. Internally, the plugin loader loops through each prefix, and then through each path attached to it, testing to see if the file exists and is readable on that path. It then loads it, and tests to see that the class it is looking for is available. As you might imagine, this can lead to many stat calls on the file system.

Multiply this by the number of components that use the PluginLoader, and you get an idea of the scope of this issue. At the time of this writing, the following components made use of the PluginLoader:

  • Zend_Controller_Action_HelperBroker: helpers

  • Zend_Dojo: view helpers, form elements and decorators

  • Zend_File_Transfer: adapters

  • Zend_Filter_Inflector: filters (used by the ViewRenderer action helper and Zend_Layout)

  • Zend_Filter_Input: filters and validators

  • Zend_Form: elements, validators, filters, decorators, captcha and file transfer adapters

  • Zend_Paginator: adapters

  • Zend_View: helpers, filters

How can you reduce the number of such calls made?

Use the PluginLoader include file cache

Zend Framework 1.7.0 adds an include file cache to the PluginLoader. This functionality writes " include_once()" calls to a file, which you can then include in your bootstrap. While this introduces extra include_once() calls to your code, it also ensures that the PluginLoader returns as early as possible.

The PluginLoader documentation includes a complete example of its use.

介绍
Zend Framework Performance Guide
Zend Framework手册 中文版
Zend_Db Performance
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Performance Guide
  • 介绍
  • Class Loading
  • Zend_Db Performance
  • Internationalization (i18n) and Localization (l10n)
  • View Rendering


Zend_Db Performance - Zend Framework Manual

Class Loading
Zend Framework Performance Guide
Zend Framework手册 中文版
Internationalization (i18n) and Localization (l10n)

Zend_Db Performance

Zend_Db is a database abstraction layer, and is intended to provide a common API for SQL operations. Zend_Db_Table is a Table Data Gateway, intended to abstract common table-level database operations. Due to their abstract nature and the "magic" they do under the hood to perform their operations, they can sometimes introduce performance overhead.

How can I reduce overhead introduced by Zend_Db_Table for retrieving table metadata?

In order to keep usage as simple as possible, and also to support constantly changing schemas during development, Zend_Db_Table does some magic under the hood: on first use, it fetches the table schema and stores it within object members. This operation is typically expensive, regardless of the database -- which can contribute to bottlenecks in production.

Fortunately, there are techniques for improving the situation.

Use the metadata cache

Zend_Db_Table can optionally utilize Zend_Cache to cache table metadata. This is typically faster to access and less expensive than fetching the metadata from the database itself.

The Zend_Db_Table documentation includes information on metadata caching.

Hardcode your metadata in the table definition

As of 1.7.0, Zend_Db_Table also provides support for hardcoding metadata in the table definition. This is an advanced use case, and should only be used when you know the table schema is unlikely to change, or that you're able to keep the definitions up-to-date.

SQL generated with Zend_Db_Select s not hitting my indexes; how can I make it better?

Zend_Db_Select is relatively good at its job. However, if you are performing complex queries requiring joins or sub-selects, it can often be fairly naive.

Write your own tuned SQL

The only real answer is to write your own SQL; Zend_Db does not require the usage of Zend_Db_Select, so providing your own, tuned SQL select statements is a perfectly legitimate approach,

Run EXPLAIN on your queries, and test a variety of approaches until you can reliably hit your indices in the most performant way -- and then hardcode the SQL as a class property or constant.

If the SQL requires variable arguments, provide placeholders in the SQL, and utilize a combination of vsprintf() and array_walk() to inject the values into the SQL:

  1. // $adapter is the DB adapter. In Zend_Db_Table, retrieve
  2. // it using $this->getAdapter().
  3. $sql = vsprintf(
  4.     self::SELECT_FOO,
  5.     array_walk($values, array($adapter, 'quoteInto'))
  6. );
Class Loading
Zend Framework Performance Guide
Zend Framework手册 中文版
Internationalization (i18n) and Localization (l10n)
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Performance Guide
  • 介绍
  • Class Loading
  • Zend_Db Performance
  • Internationalization (i18n) and Localization (l10n)
  • View Rendering


Internationalization (i18n) and Localization (l10n) - Zend Framework Manual

Zend_Db Performance
Zend Framework Performance Guide
Zend Framework手册 中文版
View Rendering

Internationalization (i18n) and Localization (l10n)

Internationalizing and localizing a site are fantastic ways to expand your audience and ensure that all visitors can get to the information they need. However, it often comes with a performance penalty. Below are some strategies you can employ to reduce the overhead of i18n and l10n.

Which translation adapter should I use?

Not all translation adapters are made equal. Some have more features than others, and some perform better than others. Additionally, you may have business requirements that force you to use a particular adapter. However, if you have a choice, which adapters are fastest?

Use non-XML translation adapters for greatest speed

Zend Framework ships with a variety of translation adapters. Fully half of them utilize an XML format, incurring memory and performance overhead. Fortunately, there are several adapters that utilize other formats that can be parsed much more quickly. In order of speed, from fastest to slowest, they are:

  • Array: this is the fastest, as it is, by definition, parsed into a native PHP format immediately on inclusion.

  • CSV: uses fgetcsv() to parse a CSV file and transform it into a native PHP format.

  • INI: uses parse_ini_file() to parse an INI file and transform it into a native PHP format. This and the CSV adapter are roughly equivalent performance-wise.

  • Gettext: The gettext adapter from Zend Framework does not use the gettext extension as it is not thread safe and does not allow specifying more than one locale per server. As a result, it is slower than using the gettext extension directly, but, because the gettext format is binary, it's faster to parse than XML.

If high performance is one of your concerns, we suggest utilizing one of the above adapters.

How can I make translation and localization even faster?

Maybe, for business reasons, you're limited to an XML-based translation adapter. Or perhaps you'd like to speed things up even more. Or perhaps you want to make l10n operations faster. How can you do this?

Use translation and localization caches

Both Zend_Translate and Zend_Locale implement caching functionality that can greatly affect performance. In the case of each, the major bottleneck is typically reading the files, not the actual lookups; using a cache eliminates the need to read the translation and/or localization files.

You can read about caching of translation and localization strings in the following locations:

  • Zend_Translate adapter caching

  • Zend_Locale caching

Zend_Db Performance
Zend Framework Performance Guide
Zend Framework手册 中文版
View Rendering
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Performance Guide
  • 介绍
  • Class Loading
  • Zend_Db Performance
  • Internationalization (i18n) and Localization (l10n)
  • View Rendering


View Rendering - Zend Framework Manual

Internationalization (i18n) and Localization (l10n)
Zend Framework Performance Guide
Zend Framework手册 中文版
版权信息

View Rendering

When using Zend Framework's MVC layer, chances are you will be using Zend_View. Zend_View is performs well compared to other view or templating engines; since view scripts are written in PHP, you do not incur the overhead of compiling custom markup to PHP, nor do you need to worry that the compiled PHP is not optimized. However, Zend_View presents its own issues: extension is done via overloading (view helpers), and a number of view helpers, while carrying out key functionality do so with a performance cost.

How can I speed up resolution of view helpers?

Most Zend_View "methods" are actually provided via overloading to the helper system. This provides important flexibility to Zend_View; instead of needing to extend Zend_View and provide all the helper methods you may utilize in your application, you can define your helper methods in separate classes and consume them at will as if they were direct methods of Zend_View. This keeps the view object itself relatively thin, and ensures that objects are created only when needed.

Internally, Zend_View uses the PluginLoader to look up helper classes. This means that for each helper you call, Zend_View needs to pass the helper name to the PluginLoader, which then needs to determine the class name, load the class file if necessary, and then return the class name so it may be instantiated. Subsequent uses of the helper are much faster, as Zend_View keeps an internal registry of loaded helpers, but if you use many helpers, the calls add up.

The question, then, is: how can you speed up helper resolution?

Use the PluginLoader include file cache

The simplest, cheapest solution is the same as for general PluginLoader performance: use the PluginLoader include file cache. Anecdotal evidence has shown this technique to provide a 25-30% performance gain on systems without an opcode cache, and a 40-65% gain on systems with an opcode cache.

Extend Zend_View to provide often used helper methods

Another solution for those seeking to tune performance even further is to extend Zend_View to manually add the helper methods they most use in their application. Such helper methods may simply manually instantiate the appropriate helper class and proxy to it, or stuff the full helper implementation into the method.

  1. class My_View extends Zend_View
  2. {
  3.     /**
  4.      * @var array Registry of helper classes used
  5.      */
  6.     protected $_localHelperObjects = array();
  7.
  8.     /**
  9.      * Proxy to url view helper
  10.      *
  11.      * @param  array $urlOptions Options passed to the assemble method
  12.      *                           of the Route object.
  13.      * @param  mixed $name The name of a Route to use. If null it will
  14.      *                     use the current Route
  15.      * @param  bool $reset Whether or not to reset the route defaults
  16.      *                     with those provided
  17.      * @return string Url for the link href attribute.
  18.      */
  19.     public function url(array $urlOptions = array(), $name = null,
  20.         $reset = false, $encode = true
  21.     ) {
  22.         if (!array_key_exists('url', $this->_localHelperObjects)) {
  23.             $this->_localHelperObjects['url'] = new Zend_View_Helper_Url();
  24.             $this->_localHelperObjects['url']->setView($this);
  25.         }
  26.         $helper = $this->_localHelperObjects['url'];
  27.         return $helper->url($urlOptions, $name, $reset, $encode);
  28.     }
  29.
  30.     /**
  31.      * Echo a message
  32.      *
  33.      * Direct implementation.
  34.      *
  35.      * @param  string $string
  36.      * @return string
  37.      */
  38.     public function message($string)
  39.     {
  40.         return "<h1>" . $this->escape($message) . "</h1>\n";
  41.     }
  42. }

Either way, this technique will substantially reduce the overhead of the helper system by avoiding calls to the PluginLoader entirely, and either benefiting from autoloading or bypassing it altogether.

How can I speed up view partials?

Those who use partials heavily and who profile their applications will often immediately notice that the partial() view helper incurs a lot of overhead, due to the need to clone the view object. Is it possible to speed this up?

Use partial() only when really necessary

The partial() view helper accepts three arguments:

  • $name: the name of the view script to render

  • $module: the name of the module in which the view script resides; or, if no third argument is provided and this is an array or object, it will be the $model argument.

  • $model: an array or object to pass to the partial representing the clean data to assign to the view.

The power and use of partial() come from the second and third arguments. The $module argument allows partial() to temporarily add a script path for the given module so that the partial view script will resolve to that module; the $model argument allows you to explicitly pass variables for use with the partial view. If you're not passing either argument, use render() instead!

Basically, unless you are actually passing variables to the partial and need the clean variable scope, or rendering a view script from another MVC module, there is no reason to incur the overhead of partial(); instead, use Zend_View's built-in render() method to render the view script.

How can I speed up calls to the action() view helper?

Version 1.5.0 introduced the action() view helper, which allows you to dispatch an MVC action and capture its rendered content. This provides an important step towards the DRY principle, and promotes code reuse. However, as those who profile their applications will quickly realize, it, too, is an expensive operation. Internally, the action() view helper needs to clone new request and response objects, invoke the dispatcher, invoke the requested controller and action, etc.

How can you speed it up?

Use the ActionStack when possible

Introduced at the same time as the action() view helper, the ActionStack consists of an action helper and a front controller plugin. Together, they allow you to push additional actions to invoke during the dispatch cycle onto a stack. If you are calling action() from your layout view scripts, you may want to instead use the ActionStack, and render your views to discrete response segments. As an example, you could write a dispatchLoopStartup() plugin like the following to add a login form box to each page:

  1. class LoginPlugin extends Zend_Controller_Plugin_Abstract
  2. {
  3.     protected $_stack;
  4.
  5.     public function dispatchLoopStartup(
  6.         Zend_Controller_Request_Abstract $request
  7.     ) {
  8.         $stack = $this->getStack();
  9.         $loginRequest = new Zend_Controller_Request_Simple();
  10.         $loginRequest->setControllerName('user')
  11.                      ->setActionName('index')
  12.                      ->setParam('responseSegment', 'login');
  13.         $stack->pushStack($loginRequest);
  14.     }
  15.
  16.     public function getStack()
  17.     {
  18.         if (null === $this->_stack) {
  19.             $front = Zend_Controller_Front::getInstance();
  20.             if (!$front->hasPlugin('Zend_Controller_Plugin_ActionStack')) {
  21.                 $stack = new Zend_Controller_Plugin_ActionStack();
  22.                 $front->registerPlugin($stack);
  23.             } else {
  24.                 $stack = $front->getPlugin('ActionStack')
  25.             }
  26.             $this->_stack = $stack;
  27.         }
  28.         return $this->_stack;
  29.     }
  30. }

The UserController::indexAction() method might then use the $responseSegment parameter to indicate which response segment to render to. In the layout script, you would then simply render that response segment:

  1. <?php $this->layout()->login ?>

While the ActionStack still requires a dispatch cycle, this is still cheaper than the action() view helper as it does not need to clone objects and reset internal state. Additionally, it ensures that all pre and post dispatch plugins are invoked, which may be of particular concern if you are using front controller plugins for handling ACL's to particular actions.

Favor helpers that query the model over action()

In most cases, using action() is simply overkill. If you have most business logic nested in your models and are simply querying the model and passing the results to a view script, it will typically be faster and cleaner to simply write a view helper that pulls the model, queries it, and does something with that information.

As an example, consider the following controller action and view script:

  1. class BugController extends Zend_Controller_Action
  2. {
  3.     public function listAction()
  4.     {
  5.         $model = new Bug();
  6.         $this->view->bugs = $model->fetchActive();
  7.     }
  8. }
  9.
  10. // bug/list.phtml:
  11. echo "<ul>\n";
  12. foreach ($this->bugs as $bug) {
  13.     printf("<li><b>%s</b>: %s</li>\n",
  14.         $this->escape($bug->id),
  15.         $this->escape($bug->summary)
  16.     );
  17. }
  18. echo "</ul>\n";

Using action(), you would then invoke it with the following:

  1. <?php $this->action('list', 'bug') ?>

This could be refactored to a view helper that looks like the following:

  1. class My_View_Helper_BugList extends Zend_View_Helper_Abstract
  2. {
  3.     public function bugList()
  4.     {
  5.         $model = new Bug();
  6.         $html  = "<ul>\n";
  7.         foreach ($model->fetchActive() as $bug) {
  8.             $html .= sprintf(
  9.                 "<li><b>%s</b>: %s</li>\n",
  10.                 $this->view->escape($bug->id),
  11.                 $this->view->escape($bug->summary)
  12.             );
  13.         }
  14.         $html .= "</ul>\n";
  15.         return $html;
  16.     }
  17. }

You would then invoke the helper as follows:

  1. <?php $this->bugList() ?>

This has two benefits: it no longer incurs the overhead of the action() view helper, and also presents a more semantically understandable API.

Internationalization (i18n) and Localization (l10n)
Zend Framework Performance Guide
Zend Framework手册 中文版
版权信息
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Performance Guide
  • 介绍
  • Class Loading
  • Zend_Db Performance
  • Internationalization (i18n) and Localization (l10n)
  • View Rendering


版权信息 - Zend Framework Manual

View Rendering

版权信息

以下版权信息适用于部分Zend Framework。

Copyright © 2005- Zend Technologies Inc. (http://www.zend.com)

View Rendering
Zend Framework手册 中文版
Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework简介
  • Learning Zend Framework
  • Zend Framework Reference
  • 系统需求
  • Zend Framework Migration Notes
  • Zend Framework 的 PHP 编码标准
  • Zend Framework Documentation Standard
  • Recommended Project Structure for Zend Framework MVC Applications
  • Zend Framework Performance Guide
  • 版权信息


Zend_Config_Writer - Zend Framework Manual

Zend_Config_Xml
Zend Framework Reference
Zend Framework手册 中文版
Zend_Config_Writer

Zend_Config_Writer

Table of Contents
  • Zend_Config_Writer
Zend_Config_Xml
Zend Framework Reference
Zend Framework手册 中文版
Zend_Config_Writer
  • Zend Framework手册 中文版
  • Zend Framework手册 中文版
  • Zend Framework Reference
  • Zend_Acl
  • Zend_Amf
  • Zend_Application
  • Zend_Auth
  • Zend_Barcode
  • Zend_Cache
  • Zend_Captcha
  • Zend_CodeGenerator
  • Zend_Config
  • Zend_Config_Writer
  • Zend_Console_Getopt
  • Zend_Controller
  • Zend_Currency
  • Zend_Date
  • Zend_Db
  • Zend_Debug
  • Zend_Dojo
  • Zend_Dom
  • Zend_Exception
  • Zend_Feed
  • Zend_File
  • Zend_Filter
  • Zend_Form
  • Zend_Gdata
  • Zend_Http
  • Zend_InfoCard
  • Zend_Json
  • Zend_Layout
  • Zend_Ldap
  • Zend_Loader
  • Zend_Locale
  • Zend_Log
  • Zend_Mail
  • Zend_Markup
  • Zend_Measure
  • Zend_Memory
  • Zend_Mime
  • Zend_Navigation
  • Zend_Oauth
  • Zend_OpenId
  • Zend_Paginator
  • Zend_Pdf
  • Zend_ProgressBar
  • Zend_Queue
  • Zend_Reflection
  • Zend_Registry
  • Zend_Rest
  • Zend_Search_Lucene
  • Zend_Serializer
  • Zend_Server
  • Zend_Service
  • Zend_Session
  • Zend_Soap
  • Zend_Tag
  • Zend_Test
  • Zend_Text
  • Zend_TimeSync
  • Zend_Tool
  • Zend_Tool_Framework
  • Zend_Tool_Project
  • Zend_Translate
  • Zend_Uri
  • Zend_Validate
  • Zend_Version
  • Zend_View
  • Zend_Wildfire
  • Zend_XmlRpc
  • ZendX_Console_Process_Unix
  • ZendX_JQuery