Zend Framework 1 – Quick Start

创建 Zend 项目

若果创造 Zend 项目,首先使下载并解压 Zend Framework。

安装 Zend Framework

下载最新的 Zend Framework 1.12.20
源码包,(我们下的是
Zend Framework 1,所以下面的内容还是根据 Zend 1)

解压到相当的地方(比如:/home/xxx/bin/).

注: /home/xxx/bin
是本身宠的目,如果你设定了上下一心之目,就活该替换下发号施令中相应的地方

$ tar -xzvf ZendFramework-1.12.20.tar.gz -C /home/xxx/bin

然 Zend Framework 就设置在了 /home/xxx/bin/ZendFramework-1.12.20

注1:Zend Framework
各个版本下载
注2:$ 符号表示即条件是 Linux 命令行终端,在守候输入一个口命令。

创立项目

当 Zend 安装目录下之 bin/ 目录下发出 zf.sh
脚本文件,你需要以系统path目录下创办该文件的链接,然后便得以命令行中任何地方用zf命令创建项目了。

$ sudo ln -s /home/xxx/bin/ZendFramework-1.12.20/bin/zf.sh /usr/local/bin/zf

开辟命令执行(Ctrl + Alt + T),切换到您想创造项目之职务,假如你想当 ~/demo/
目录下创造 Zend 项目:cd ~/demo/

履下的指令创建 quickstart 项目:

$ zf create project quickstart

这样尽管创办了 /home/xxx/demo/quickstart,并且于 quickstart
目录下自行创建了 Zend 项目之组成部分目录结构。其色组织如下:

quickstart
|-- application
|   |-- Bootstrap.php
|   |-- configs
|   |   `-- application.ini
|   |-- controllers
|   |   |-- ErrorController.php
|   |   `-- IndexController.php
|   |-- models
|   `-- views
|       |-- helpers
|       `-- scripts
|           |-- error
|           |   `-- error.phtml
|           `-- index
|               `-- index.phtml
|-- library
|-- public
|   |-- .htaccess
|   `-- index.php
`-- tests
    |-- application
    |   `-- bootstrap.php
    |-- library
    |   `-- bootstrap.php
    `-- phpunit.xml

这时候,只是创建了 Zend 项目布局,你还待把 Zend Framework 添加到
quickstart 项目面临,有三三两两栽方式,一中是创建一个链接,把 zend 框架下之
library 目录链接到 quickstart/library ,另一样栽方式是直接复制 zend
框架下的 library 目录替换掉 quickstart/library。

# Symlink
$ cd library
$ ln -s /home/xxx/bin/ZendFramework-1.12.20/library/Zend .

# or copy
$ cd library
$ cp -r /home/xxx/bin/ZendFramework-1.12.20/library/Zend .

诸如此类就可以看到 quickstart/library/Zend 目录了。

种启动文件

Bootstrap 类定义了 Zend 项目启动时如初始化的资源以及组件。默认地,Zend
Framework 初始化了 Front Controller,然后其使 application/controllers/
作为找 action controller 的默认路径。这个近乎如下:

// application/Bootstrap.php

class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
}

设您所呈现,这其间没啊内容。

种安排文件

默认配置文件在:application/configs/application.ini,包含有为主的一声令下,比如设置php环境,设置启动类,设置
action controller 等。文件内容如下:

; application/configs/application.ini

[production]
phpSettings.display_startup_errors = 0
phpSettings.display_errors = 0
includePaths.library = APPLICATION_PATH "/../library"
bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
bootstrap.class = "Bootstrap"
appnamespace = "Application"
resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"
resources.frontController.params.displayExceptions = 0

[staging : production]

[testing : production]
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1

[development : production]
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1

关于这个文件发出几乎单中心:

(1) 使用 ini 配置文件时,你得一直引用常量,APPLICATION_PATH
就是一个常量。

(2) 这个文件被分为几只有:production,staging,testing 和
development。后面三个包括了 production
的设置。不同之条件其配备分开,这样便于开发和调节。

Action Controller 控制器

应用程序的 action controller 定义了程序流程,把用户要映射到合适的
model 和 view。

一个 action controller
应包含一个或者多只为Action最后的主意,这些点子好通过 web
请求访问到。默认地,Zend Framework URLs 遵循 /controller/action
的模式,其中 controller 就投 action controller
名字(以Controller作为后缀),而 action 就投到 action
方法(以Action作为后缀)。

普普通通,需要一个 IndexController,它象征网站首页,和一个
ErrorController,它代表如 HTTP404、HTTP500 等误页面.

初始 IndexController 代码如下:

// application/controllers/IndexController.php

class IndexController extends Zend_Controller_Action
{

    public function init()
    {
        /* Initialize action controller here */
    }

    public function indexAction()
    {
        // action body
    }
}

初始 ErrorController 代码如下:

// application/controllers/ErrorController.php

class ErrorController extends Zend_Controller_Action
{

    public function errorAction()
    {
        $errors = $this->_getParam('error_handler');

        switch ($errors->type) {
            case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ROUTE:
            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()->setHttpResponseCode(404);
                $this->view->message = 'Page not found';
                break;
            default:
                // application error
                $this->getResponse()->setHttpResponseCode(500);
                $this->view->message = 'Application error';
                break;
        }

        $this->view->exception = $errors->exception;
        $this->view->request   = $errors->request;
    }
}

Views 视图

Zend Framework 中之 Views 是用寻常 PHP 代码写的。View scripts 在
application/views/scripts/
下面,它因为控制器名字分文件夹组织起。本例中,我们来一个 IndexController
和 ErrorController,因此相应地,也承诺以 View scripts 目录下发生 index/ 和
error/ 子目录。在这子目录中,又发每个 view scripts 文件,对承诺
Controller 中之 Action。本例中,使用 index/index.phtml 和
error/error.phtml。

脚是默认的 index/index.phtml view script:

<!-- application/views/scripts/index/index.phtml -->
<style>

    a:link,
    a:visited
    {
        color: #0398CA;
    }

    span#zf-name
    {
        color: #91BE3F;
    }

    div#welcome
    {
        color: #FFFFFF;
        background-image: url(http://framework.zend.comkg_header.jpg);
        width:  600px;
        height: 400px;
        border: 2px solid #444444;
        overflow: hidden;
        text-align: center;
    }

    div#more-information
    {
        background-image: url(http://framework.zend.comkg_body-bottom.gif);
        height: 100%;
    }

</style>
<div id="welcome">
    <h1>Welcome to the Zend Framework!<h1 />
    <h3>This is your project's main page<h3 />
    <div id="more-information">
        <p>
            <img src="http://framework.zend.comPoweredBy_ZF_4LightBG.png" />
        </p>

        <p>
            Helpful Links: <br />
            <a href="http://framework.zend.com/">Zend Framework Website</a> |
            <a href="http://framework.zend.com/manual/en/">Zend Framework
                Manual</a>
        </p>
    </div>
</div>

error/error.phtml 稍微复杂一点,其中使用了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 xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>Zend Framework Default Application</title>
</head>
<body>
  <h1>An error occurred</h1>
  <h2><?php echo $this->message ?></h2>

  <?php if ('development' == $this->env): ?>

  <h3>Exception information:</h3>
  <p>
      <b>Message:</b> <?php echo $this->exception->getMessage() ?>
  </p>

  <h3>Stack trace:</h3>
  <pre><?php echo $this->exception->getTraceAsString() ?>
  </pre>

  <h3>Request Parameters:</h3>
  <pre><?php echo var_export($this->request->getParams(), 1) ?>
  </pre>
  <?php endif ?>

</body>
</html>

创立虚拟主机

对 quickstart 项目,我们将其座落 apache 服务器上运行。

我们要安装一个虚拟主机,这样便足以当浏览器中输入域名来访问我们的网站了。假设你曾经布置好了
php+apache+mysql
运行环境,如果没,请参考教程

一旦我们的种所投的域名是:quickstart.local。

登 apache 配置目录,创建布局文件:

cd /etc/apache2/sites-available/
sudo gedit quickstart.local.conf

下一场复制下面的情到拖欠配置文件,注意:项目路线需要替换成你自己之门类路线:

<VirtualHost *:80>
    ServerName quickstart.local

    ServerAdmin webmaster@localhost
    DocumentRoot /home/xxx/demo/quickstart/public

    <Directory /home/xxx/demo/quickstart/public>
    AllowOverride all
    require all granted
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

</VirtualHost>

保存该公文,并且启用该配置:sudo a2ensite quickstart.local

然后打开hosts文件:sudo gedit /etc/hosts 添加一行:
127.0.0.1 quickstart.local

最后又开一下 apache 服务器:
sudo service apache2 restart

暨是结束,这个项目即使创办成功还要可运行了。

检查成果

而今便好拜你的品类网站了,打开浏览器输入http://quickstart.local,就会收看欢迎页了。

兴许遇到的题目:

  1. 页面不出示:很有或时时路目录的权问题,使用
    chmod -R 777 /home/xxx/demo/quickstart 试试看。

创建一个 Layout

而也许注意到,上面的 view scripts 不是整的 html
页面,这是明知故犯设计之。我们特想吃 action 只回 action
本身要出口的情,而无是整套应用程序页面。

今日来做一个总体的 HTML 页面。我们用一个大局的 layout
来作为网站联合的样式。

注: 下面的一声令下若任由证明,默认是在当前档根本目录下实施之。

启运用 Zend_Layout,首先被 bootstrap 来加以载 Layout
资源。通过下面的吩咐可实现:

$zf enable layout
# Layouts have been enabled, and a default layout created at
# application/layouts/scripts/layout.phtml
# A layout entry has been added to the application config file.

此时,application/configs/application.ini 内容自动更新了:

; application/configs/application.ini

; Add to [production] section:
resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts"

这个命令告诉应用程序去 application/layouts/scripts 去寻找 layout。

俺们还要启用 XHTML DocType 声明,为夫,在 bootstrap 中加载该资源。在
bootstrap中上加资源的最简易的法就是创造一个为init开头的计。此时,我们利用
_initDoctype() 方法来初始化 doctype:

// application/Bootstrap.php

class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
    protected function _initDoctype()
    {
    }
}

来矣这艺术,还需要为 view 使用对的 doctype,但是 view
从何来?最简单易行的法门就是初始化 View 资源;有矣她,就得管 view
对象放入 bootstrap 并应用它。

丰富下行到 aplication/configs/application.ini 来创造 view 资源:

; application/configs/application.ini

; Add to [production] section:
resources.view[] =

下一场再度来增加一下 _initDoctype() 方法。

// application/Bootstrap.php

class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
    protected function _initDoctype()
    {
        $this->bootstrap('view');
        $view = $this->getResource('view');
        $view->doctype('XHTML1_STRICT');
    }
}

接下来,创建全局的 layout:

<!-- application/layouts/scripts/layout.phtml -->
<?php echo $this->doctype() ?>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>Zend Framework Quickstart Application</title>
  <?php echo $this->headLink()->appendStylesheet('/css/global.css') ?>
</head>
<body>
<div id="header" style="background-color: #EEEEEE; height: 30px;">
    <div id="header-logo" style="float: left">
        <b>ZF Quickstart Application</b>
    </div>
    <div id="header-navigation" style="float: right">
        <a href="<?php echo $this->url(
            array('controller'=>'guestbook'),
            'default',
            true) ?>">Guestbook</a>
    </div>
</div>

<?php echo $this->layout()->content ?>

</body>
</html>

使用headLink()来生成<link>元素。

现今再打开浏览器并查看源代码,应该能够见到
XHTML头部,<head> <title> <body>等部分。


开创一个 Model 和 Database Table

今天考虑一下guestbook的结合,它含有笔录,每个记录由注释,时间穿,email地址等做。我们把它在数据库里,并出一个唯一id。我们期望能保留、获取具有记录。

从而,一个简的 guestbook 模型 API 就如下这样:

// application/models/Guestbook.php

class Application_Model_Guestbook
{
    protected $_comment;
    protected $_created;
    protected $_email;
    protected $_id;

    public function __set($name, $value);
    public function __get($name);

    public function setComment($text);
    public function getComment();

    public function setEmail($email);
    public function getEmail();

    public function setCreated($ts);
    public function getCreated();

    public function setId($id);
    public function getId();
}

class Application_Model_GuestbookMapper
{
    public function save(Application_Model_Guestbook $guestbook);
    public function find($id);
    public function fetchAll();
}
}

下,我们好开思索如何设置数据库了。

第一使初始化 Db 资源。使用 zf configure db-adapter 命令:

zf configure db-adapter "adapter=Pdo_MySql&host=localhost&username=root&password=&dbname=guestbook" production

zf configure db-adapter "adapter=Pdo_MySql&host=localhost&username=root&password=&dbname=guestbook-test" testing

zf configure db-adapter "adapter=Pdo_MySql&host=localhost&username=root&password=&dbname=guestbook-dev" development

万一成功实践,那么在 application/configs/application.ini
中虽可知顾新增的几乎履安排:

//application/configs/application.ini

resources.db.adapter = "Pdo_MySql"
resources.db.params.host = "localhost"
resources.db.params.username = "root"
resources.db.params.password = ""
resources.db.params.dbname ="guestbook" 

注:设将数据库密码设置成你自己之。

下一场创建数据库,打开 phpMyadmin,创建数量库
guestbook,输入下面SQL语句并尽:

CREATE TABLE IF NOT EXISTS `guestbook` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `email` varchar(32) NOT NULL DEFAULT 'noemail@test.com',
    `comment` varchar(200) NOT NULL,
    `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

联网下去我们应用 Table Data
Gateway
机制来连续数据源。Zend_Db_Table 提供了此功效。

首先创建一个 Zend_Db_Table 类:

$ zf create db-table Guestbook guestbook

翻项目结构,发现多了一个 application/models/DbTable/
目录,里面有一个 Guestbook.php 文件。其情节如下:

// application/models/DbTable/Guestbook.php

/**
* This is the DbTable class for the guestbook table.
*/
class Application_Model_DbTable_Guestbook extends Zend_Db_Table_Abstract
{
    /** Table name */
    protected $_name    = 'guestbook';
}

注意 Application_Model_DbTable 类前缀,它对应
application/models/DbTable 目录。

然后创建一个 Data
Mapper。Data Mapper
映射对象到数据库。本例中,它将映射 model 到数据源。

$ zf create model GuestbookMapper

接下来打开 application/models/GuestbookMapper.php 并输入以下内容:

// application/models/GuestbookMapper.php

class Application_Model_GuestbookMapper
{
    protected $_dbTable;

    public function setDbTable($dbTable)
    {
        if (is_string($dbTable)) {
            $dbTable = new $dbTable();
        }
        if (!$dbTable instanceof Zend_Db_Table_Abstract) {
            throw new Exception('Invalid table data gateway provided');
        }
        $this->_dbTable = $dbTable;
        return $this;
    }

    public function getDbTable()
    {
        if (null === $this->_dbTable) {
            $this->setDbTable('Application_Model_DbTable_Guestbook');
        }
        return $this->_dbTable;
    }

    public function save(Application_Model_Guestbook $guestbook)
    {
        $data = array(
            'email'   => $guestbook->getEmail(),
            'comment' => $guestbook->getComment(),
            'created' => date('Y-m-d H:i:s'),
        );

        if (null === ($id = $guestbook->getId())) {
            unset($data['id']);
            $this->getDbTable()->insert($data);
        } else {
            $this->getDbTable()->update($data, array('id = ?' => $id));
        }
    }

    public function find($id, Application_Model_Guestbook $guestbook)
    {
        $result = $this->getDbTable()->find($id);
        if (0 == count($result)) {
            return;
        }
        $row = $result->current();
        $guestbook->setId($row->id)
                  ->setEmail($row->email)
                  ->setComment($row->comment)
                  ->setCreated($row->created);
    }

    public function fetchAll()
    {
        $resultSet = $this->getDbTable()->fetchAll();
        $entries   = array();
        foreach ($resultSet as $row) {
            $entry = new Application_Model_Guestbook();
            $entry->setId($row->id)
                  ->setEmail($row->email)
                  ->setComment($row->comment)
                  ->setCreated($row->created);
            $entries[] = $entry;
        }
        return $entries;
    }
}

当今,创建 model 类,仍然以 zf 命令:

$ zf create model Guestbook

打开刚刚创建的模型类: application/models/Guestbook.php 并上加以下代码:

// application/models/Guestbook.php

class Application_Model_Guestbook
{
    protected $_comment;
    protected $_created;
    protected $_email;
    protected $_id;

    public function __construct(array $options = null)
    {
        if (is_array($options)) {
            $this->setOptions($options);
        }
    }

    public function __set($name, $value)
    {
        $method = 'set' . $name;
        if (('mapper' == $name) || !method_exists($this, $method)) {
            throw new Exception('Invalid guestbook property');
        }
        $this->$method($value);
    }

    public function __get($name)
    {
        $method = 'get' . $name;
        if (('mapper' == $name) || !method_exists($this, $method)) {
            throw new Exception('Invalid guestbook property');
        }
        return $this->$method();
    }

    public function setOptions(array $options)
    {
        $methods = get_class_methods($this);
        foreach ($options as $key => $value) {
            $method = 'set' . ucfirst($key);
            if (in_array($method, $methods)) {
                $this->$method($value);
            }
        }
        return $this;
    }

    public function setComment($text)
    {
        $this->_comment = (string) $text;
        return $this;
    }

    public function getComment()
    {
        return $this->_comment;
    }

    public function setEmail($email)
    {
        $this->_email = (string) $email;
        return $this;
    }

    public function getEmail()
    {
        return $this->_email;
    }

    public function setCreated($ts)
    {
        $this->_created = $ts;
        return $this;
    }

    public function getCreated()
    {
        return $this->_created;
    }

    public function setId($id)
    {
        $this->_id = (int) $id;
        return $this;
    }

    public function getId()
    {
        return $this->_id;
    }
}

末段,我们创建一个 guestbook controller 查询并出示数据库中之结果:

$ zf create controller Guestbook

立即将创 application/controllers/GuestbookController.php,它发一个
IndexAction 方法,同时,在 application/views/scripts/guestbook
目录中创造了一个 index.phtml 文件。

打开 GuestbookController,在 IndexAction 中补充加代码,显示有的
guestbook 记录:

// application/controllers/GuestbookController.php

class GuestbookController extends Zend_Controller_Action
{
    public function indexAction()
    {
        $guestbook = new Application_Model_GuestbookMapper();
        $this->view->entries = $guestbook->fetchAll();
    }
}

打开 application/views/scripts/guestbook/index.phtml 添加以下内容:

<!-- application/views/scripts/guestbook/index.phtml -->

<p><a href="<?php echo $this->url(
    array(
        'controller' => 'guestbook',
        'action'     => 'sign'
    ),
    'default',
    true) ?>">Sign Our Guestbook</a></p>

Guestbook Entries: <br />
<dl>
    <?php foreach ($this->entries as $entry): ?>
    <dt><?php echo $this->escape($entry->email) ?></dt>
    <dd><?php echo $this->escape($entry->comment) ?></dd>
    <?php endforeach ?>
</dl>

切换到浏览器,打开:http://guestbook.local/guestbook
,你应该看这些情节:

发现并未数据,那就开辟
phpMyadmin,插入一些多少更看,复制下面的sql语句到phpmyadmin并推行:

INSERT INTO `guestbook`.`guestbook` (`id`, `email`, `comment`, `created`) VALUES (NULL, 'noemail@qq.com', 'good', CURRENT_TIMESTAMP),
(NULL, 'noemail2@qq.com', 'good book', CURRENT_TIMESTAMP),
(NULL, 'noemail3@qq.com', 'good book ok', CURRENT_TIMESTAMP);

刷新浏览器,结果如图所示,成功地自数据库读取数据并出示在页面及:

创建 Form

为让 guestbook 更实惠一些,我们要一个表单来交付新的褒贬起。

首先,创建一个 form 类:

$ zf create form Guestbook

开辟刚创立的 form 类 application/forms/Guestbook.php ,添加下列代码:

// application/forms/Guestbook.php

class Application_Form_Guestbook extends Zend_Form
{
    public function init()
    {
        // Set the method for the display form to POST
        $this->setMethod('post');

        // Add an email element
        $this->addElement('text', 'email', array(
            'label'      => 'Your email address:',
            'required'   => true,
            'filters'    => array('StringTrim'),
            'validators' => array(
                'EmailAddress',
            )
        ));

        // Add the comment element
        $this->addElement('textarea', 'comment', array(
            'label'      => 'Please Comment:',
            'required'   => true,
            'validators' => array(
                array('validator' => 'StringLength', 'options' => array(0, 20))
                )
        ));

        // Add a captcha
        $this->addElement('captcha', 'captcha', array(
            'label'      => 'Please enter the 5 letters displayed below:',
            'required'   => true,
            'captcha'    => array(
                'captcha' => 'Figlet',
                'wordLen' => 5,
                'timeout' => 300
            )
        ));

        // Add the submit button
        $this->addElement('submit', 'submit', array(
            'ignore'   => true,
            'label'    => 'Sign Guestbook',
        ));

        // And finally add some CSRF protection
        $this->addElement('hash', 'csrf', array(
            'ignore' => true,
        ));
    }
}

地方代码定义了五独元素:email地址,评论输入框,验证码,提交按钮和CSRF保护字段。

下一步,添加 signAction
GuestbookController,它用来拍卖表单提交页面。使用 zf 命令创建:

$ zf create action sign Guestbook

创立了 signAction 和对应的 view script.

然后上加有代码到
signAction,首先检查是否生POST或GET请求,然后一旦无就简单地出示表单,若发生,则证明提交的数,并保存到数据库被

// application/controllers/GuestbookController.php

class GuestbookController extends Zend_Controller_Action
{
    // snipping indexAction()...

    public function signAction()
    {
        $request = $this->getRequest();
        $form    = new Application_Form_Guestbook();

        if ($this->getRequest()->isPost()) {
            if ($form->isValid($request->getPost())) {
                $comment = new Application_Model_Guestbook($form->getValues());
                $mapper  = new Application_Model_GuestbookMapper();
                $mapper->save($comment);
                return $this->_helper->redirector('index');
            }
        }

        $this->view->form = $form;
    }
}

本,还用编制一下 view
application/views/scripts/guestbook/sign.phtml

<!-- application/views/scripts/guestbook/sign.phtml -->

Please use the form below to sign our guestbook!

<?php
$this->form->setAction($this->url());
echo $this->form;

自我批评作用

今日又打开浏览器:http://quickstart.local/guestbook/sign
看看,效果如下:

填写好表单点击提交,就能顾列表已经更新了:

注:
上面的验证码有辨认很艰难,其实如果复制一下粘贴到txt文档中虽可知看明白了。

恭喜你!

而早已成地动 Zend Framework 的常用功能建立了一个简约的应用程序。Zend
Framework 内置了众零件,你可以一直用在您的档次遭到,这些零部件包括 web
services,搜索,PDF读取和创造,身份验证等等。可以在
文档参考
中找到更多系的技术细节。

转载请注明来源:http://www.cnblogs.com/feifeifanye/p/6252633.html
英文原稿链接:https://framework.zend.com/manual/1.12/en/learning.html

相关文章