我们邀请PHP安全专家 — 最新版Zend Frame的贡献者 — Chris Shiflett帮我们写一篇文章介绍一下ZF的主要细节,他爽快地答应了!

这份手把手的完整教程提供了用ZF构建实例的方法,并教你如何编写一个新闻管理系统。

在我们的论坛上讨论ZF和这篇教程。

Brain Bulb

Zend Framework发布了!虽然仍处于开发初期,这个教程仍突出讲解目前几个最好的功能,并指导你完成一个简单程序的构建。

Zend最早在社区里发布了ZF。基于同样的想法,这个教程写来用于展示ZF现有的功能。由于这个教程是在线发布,我将在ZF变化时对其进行更新,以便尽可能有效。

要求

Zend Framework要求PHP5。为了更好利用本教程的代码,你还需要Apache网页服务器。因为示范程序(一个新闻管理系统)用到了mod_rewrite

这个教程的代码可以自由下载,所以你可以自己试一下。你可以从Brain Buld的网站下载到代码:http://brainbulb.com/zend-framework-tutorial.tar.gz。

下载ZF

当你开始这篇教程时,你需要下载ZF的最新版本。你可以用浏览器手工从http://framework.zend.com/download选择tar.gzzip文件进行下载,或者使用下列命令:

$ wget http://framework.zend.com/download/tgz
$ tar -xvzf ZendFramework-0.1.2.tar.gz
提示:Zend计划提供自有PEAR通道简化下载。

一旦你下载了预览版,把library目录放到方便的地方。在这个教程,我把library重命名为lib以便有个简洁的目录结构:

app/
    views/
    controllers/
www/
    .htaccess
    index.php
lib/

www目录是文档根目录,controllersviews目录是以后会用到的空目录,而lib目录来自你下载的预览版。

开始

我要介绍的第一个组件是Zend_Controller。从很多方面看,它为你开发的程序提供了基础,同时也部分决定了Zend Framework不只是个组件的集合。但是,你在用之前需要将所有的得到的请求都放到一个简单的PHP脚本。本教程用的是mod_rewrite

mod_rewrite自身是一种艺术,但幸运的是,这个特殊的任务特别简单。如果你对mod_rewrite或Apache的一般配置不熟悉,在文档根目录下创建一个.htaccess文件,并添加以下内容:

RewriteEngine on
RewriteRule !/.(js|ico|gif|jpg|png|css)$ index.php
提示: Zend_Controller的一个TODO项目就是取消对 mod_rewrite的依赖。为了提供一个预览版的范例,本教程用了 mod_rewrite

如果你直接把这些内容添加到httpd.conf,你必须重启网页服务器。但如果你用.htaccess文件,则什么都不必做。你可以放一些具体的文本到index.php并访问任意路径如/foo/bar做一下快速测试。如你的域名为example.org,则访问http://example.org/foo/bar。

你还要设置ZF库的路径到include_path。你可以在php.ini设置,也可以直接在你的.htaccess文件放下列内容:

php_value include_path "/path/to/lib"

Zend

Zend类包含了一些经常使用的静态方法的集合。下面是唯一一个你要手工添加的类:

<?php

include 'Zend.php';

?>

一旦你包含了Zend.php,你就已经包含了Zend类的所有的类方法。用loadClass()就可以简单地加载其它类。例如,加载Zend_Controller_Front类:

<?php

include 'Zend.php';

Zend::loadClass('Zend_Controller_Front');

?>

include_path能理解loadclass()及ZF的组织和目录结构。我用它加载所有其它类。

Zend_Controller

使用这个controller非常直观。事实上,我写本教程时并没有用到它丰富的文档。

提示:文档目前已经可以在 http://framework.zend.com/manual/zend.controller.html看到。

我一开始是用一个叫Zend_Controller_Front的front controller。为了理解它是怎么工作的,请把下列代码放在你的index.php文件:

<?php

include 'Zend.php';

Zend::loadClass('Zend_Controller_Front');

$controller = Zend_Controller_Front::getInstance();
$controller->setControllerDirectory('/path/to/controllers');
$controller->dispatch();

?>

如果你更喜欢对象链结,可以用以下代码代替:

<?php

include 'Zend.php';

Zend::loadClass('Zend_Controller_Front');

$controller = Zend_Controller_Front::getInstance()
              ->setControllerDirectory('/path/to/controllers')
              ->dispatch();

?>

现在如果你访问/foo/bar,会有错误发生。没错!它让你知道发生了什么事。主要的问题是找不到IndexController.php文件。

在你创建这个文件之前,应先理解一下ZF想让你怎样组织这些事情。ZF把访问请求给拆分开来。假如访问的是/foo/bar,则foo是controller,而bar是action。它们的默认值都是index.

如果foo是controller,ZF就会去查找controllers目录下的FooController.php文件。因为这个文件不存在,ZF就退回到IndexController.php。结果都没有找到,就报错了。

接下来,在controllers目录创建IndexController.php文件(可以用setControllerDirectory()设置):

<?php

Zend::loadClass('Zend_Controller_Action');

class IndexController extends Zend_Controller_Action 
{
    public function indexAction()
    {
        echo 'IndexController::indexAction()';
    }
}

?>

就如刚才说明的,IndexController类处理来自index controller或controller不存在的请求。indexAction()方法处理action为index的访问。要记住的是index是controller和action的默认值。如果你访问//index/index/indexindexAction()方法就会被执行。 (最后面的斜杠并不会改变这个行为。) 而访问其他任何资源只会导致出错。

在继续做之前,还要在IndexController加上另外一个有用的类方法。不管什么时候访问一个不存在的控制器,都要调用noRouteAction()类方法。例如,在FooController.php不存在的条件下,访问/foo/bar就会执行noRouteAction()。但是访问/index/foo仍会出错,因为foo是action,而不是controller.

noRouteAction()添加到IndexController.php:

<?php

Zend::loadClass('Zend_Controller_Action');

class IndexController extends Zend_Controller_Action 
{
    public function indexAction()
    {
        echo 'IndexController::indexAction()';
    }

public function noRouteAction()
    {
        $this->_redirect('/');
    }
}

?>

例子中使用$this->_redirect('/')来描述执行noRouteAction()时,可能发生的行为。这会将对不存在controllers的访问重定向到根文档(首页)。

现在创建FooController.php

<?php

Zend::loadClass('Zend_Controller_Action');

class FooController extends Zend_Controller_Action 
{
    public function indexAction()
    {
        echo 'FooController::indexAction()';
    }

public function barAction()
    {
        echo 'FooController::barAction()';
    }
}

?>

如果你再次访问/foo/bar,你会发现执行了barAction(),因为bar是action。现在你不只支持了友好的URL,还可以只用几行代码就做得这么有条理。酷吧!

你也可以创建一个__call()类方法来处理像/foo/baz这样未定义的action。

<?php

Zend::loadClass('Zend_Controller_Action');

class FooController extends Zend_Controller_Action 
{
    public function indexAction()
    {
        echo 'FooController::indexAction()';
    }

public function barAction()
    {
        echo 'FooController::barAction()';
    }

public function __call($action, $arguments)
    {
        echo 'FooController:__call()';
    }
}

?>

现在你只要几行代码就可以很好地处理用户的访问了,准备好继续。

Zend_View

Zend_View是一个用来帮助你组织好你的view逻辑的类。这对于模板-系统是不可知的,为了简单起见,本教程不使用模板。如果你喜欢的话,不妨用一下。

记住,现在所有的访问都是由front controller进行处理。因此应用框架已经存在了,另外也必须遵守它。为了展示Zend_View的一个基本应用,将IndexController.php修改如下:

<?php

Zend::loadClass('Zend_Controller_Action');
Zend::loadClass('Zend_View');

class IndexController extends Zend_Controller_Action 
{
    public function indexAction()
    {
        $view = new Zend_View();
        $view->setScriptPath('/path/to/views');
        echo $view->render('example.php');
    }

public function noRouteAction()
    {
        $this->_redirect('/');
    }
}

?>

views目录创建example.php文件:

<html>
<head>
    <title>This Is an Example</title>
</head>
<body>
    <p>This is an example.</p>
</body>
</html>

现在,如果你访问自己网站的根资源,你会看到example.php的内容。这仍没什么用,但你要清楚你要在以一种结构和组织非常清楚的方式在开发网络应用。

为了让Zend_View的应用更清楚一点,,修改你的模板(example.php)包含以下内容:

<html>
<head>
    <title><?php echo $this->escape($this->title); ?></title>
</head>
<body>
    <?php echo $this->escape($this->body); ?>
</body>
</html>

现在已经添加了两个功能。$this->escape()类方法用于所有的输出。即使你自己创建输出,就像这个例子一样。避开所有输出也是一个很好的习惯,它可以在默认情况下帮助你防止跨站脚本攻击(XSS)。

$this->title$this->body属性用来展示动态数据。这些也可以在controller中定义,所以我们修改IndexController.php以指定它们:

<?php

Zend::loadClass('Zend_Controller_Action');
Zend::loadClass('Zend_View');

class IndexController extends Zend_Controller_Action 
{
    public function indexAction()
    {
        $view = new Zend_View();
        $view->setScriptPath('/path/to/views');
        $view->title = 'Dynamic Title';
        $view->body = 'This is a dynamic body.';
        echo $view->render('example.php');
    }

public function noRouteAction()
    {
        $this->_redirect('/');
    }
}

?>

现在你再次访问根目录,应该就可以看到模板所使用的这些值了。因为你在模板中使用的$this就是在Zend_View范围内所执行的实例。

要记住example.php只是一个普通的PHP脚本,所以你完全可以做你想做的。只是应努力只在要求显示数据时才使用模板。你的controller (controller分发的模块)应处理你全部的业务逻辑。

在继续之前,我想做最后一个关于Zend_View的提示。在controller的每个类方法内初始化$view对象需要额外输入一些内容,而我们的主要目标是让快速开发网络应用更简单。如果所有模板都放在一个目录下,是否要在每个例子中都调用setScriptPath()也存在争议。

幸运的是,Zend类包含了一个寄存器来帮助减少工作量。你可以用register()方法把你的$view对象存储在寄存器:

<?php

Zend::register('view', $view);

?>

registry()方法进行检索:

<?php

$view = Zend::registry('view');

?>

基于这点,本教程使用寄存器。

Zend_InputFilter

本教程讨论的最后一个组件是Zend_InputFilter。这个类提供了一种简单而有效的输入过滤方法。你可以通过提供一组待过滤数据来进行初始化。

<?php

$filterPost = new Zend_InputFilter($_POST);

?>

这会将($_POST)设置为NULL,所以就不能直接进入了。Zend_InputFilter提供了一个简单、集中的根据特定规则过滤数据的类方法集。例如,你可以用getAlpha()来获取$_POST['name']中的字母:

<?php

/* $_POST['name'] = 'John123Doe'; */

$filterPost = new Zend_InputFilter($_POST);

/* $_POST = NULL; */

$alphaName = $filterPost->getAlpha('name');

/* $alphaName = 'JohnDoe'; */

?>

每一个类方法的参数都是对应要过滤的元素的关键词。对象(例子中的$filterPost)可以保护数据不被篡改,并能更好地控制对数据的操作及一致性。因此,当你操纵输入数据,应始终使用Zend_InputFilter

提示: Zend_Filter提供与 Zend_InputFilter方法一样的静态方法。

构建新闻管理系统

虽然预览版提供了许多组件(甚至许多已经被开发),我们已经讨论了构建一个简单程序所需要的全部组件。在这里,你会对ZF的基本结构和设计有更清楚的理解。

每个人开发的程序都会有所不同,而Zend Framework试图包容这些差异。同样,这个教程是根据我的喜好写的,请根据自己的偏好自行调整。

当我开发程序时,我会先做界面。这并不意味着我把时间都花在标签、样式表和图片上,而是我从一个用户的角度去考虑问题。因此我把程序看成是页面的集合,每一页都是一个独立的网址。这个新闻系统就是由以下网址组成的:

/
/add/news
/add/comment
/admin
/admin/approve
/view/{id}

你可以直接把这些网址和controller联系起来。IndexController列出新闻,AddController添加新闻和评论,AdminController处理一些如批准新闻之类的管理,ViewController特定新闻和对应评论的显示。

如果你的FooController.php还在,把它删除。修改IndexController.php,为业务逻辑以添加相应的action和一些注释:

<?php

Zend::loadClass('Zend_Controller_Action');

class IndexController extends Zend_Controller_Action 
{
    public function indexAction()
    {
        /* List the news. */
    }

public function noRouteAction()
    {
        $this->_redirect('/');
    }
}

?>

接下来,创建AddController.php文件:

<?php

Zend::loadClass('Zend_Controller_Action');

class AddController extends Zend_Controller_Action
{
    function indexAction()
    {
        $this->_redirect('/');
    }

function commentAction()
    {
        /* Add a comment. */
    }

function newsAction()
    {
        /* Add news. */
    }

function __call($action, $arguments)
    {
        $this->_redirect('/');
    }
}

?>

记住AddControllerindexAction()方法不能调用。当访问/add时会执行这个类方法。因为用户可以手工访问这个网址,这是有可能的,所以你要把用户重定向到主页、显示错误或你认为合适的行为。

接下来,创建AdminController.php文件:

<?php

Zend::loadClass('Zend_Controller_Action');

class AdminController extends Zend_Controller_Action
{
    function indexAction()
    {
        /* Display admin interface. */
    }

function approveAction()
    {
        /* Approve news. */
    }

function __call($action, $arguments)
    {
        $this->_redirect('/');
    }
}

?>

最后,创建ViewController.php文件:

<?php

Zend::loadClass('Zend_Controller_Action');

class ViewController extends Zend_Controller_Action
{
    function indexAction()
    {
        $this->_redirect('/');
    }

function __call($id, $arguments)
    {
        /* Display news and comments for $id. */
    }
}

?>

AddController一样,index()方法不能调用,所以你可以使用你认为合适的action。ViewController和其它的有点不同,因为你不知道什么才是有效的action。为了支持像/view/23这样的网址,你要使用__call()来支持动态action。

数据库操作

因为Zend Framework的数据库组件还不稳定,而我希望这个演示可以做得简单一点。我使用了一个简单的类,用SQLite进行新闻条目和评论的存储和查询。

<?php

class Database
{
    private $_db;

public function __construct($filename)
    {
        $this->_db = new SQLiteDatabase($filename);
    }

public function addComment($name, $comment, $newsId)
    {
        $name = sqlite_escape_string($name);
        $comment = sqlite_escape_string($comment);
        $newsId = sqlite_escape_string($newsId);

$sql = "INSERT
                INTO   comments (name, comment, newsId)
                VALUES ('$name', '$comment', '$newsId')";

return $this->_db->query($sql);
    }

public function addNews($title, $content)
    {
        $title = sqlite_escape_string($title);
        $content = sqlite_escape_string($content);

$sql = "INSERT
                INTO   news (title, content)
                VALUES ('$title', '$content')";

return $this->_db->query($sql);
    }

public function approveNews($ids)
    {
        foreach ($ids as $id) {
            $id = sqlite_escape_string($id);

$sql = "UPDATE news
                    SET    approval = 'T'
                    WHERE  id = '$id'";

if (!$this->_db->query($sql)) {
                return FALSE;
            }
        }

return TRUE;
    }

public function getComments($newsId)
    {
        $newsId = sqlite_escape_string($newsId);

$sql = "SELECT name, comment
                FROM   comments
                WHERE  newsId = '$newsId'";

if ($result = $this->_db->query($sql)) {
            return $result->fetchAll();
        }

return FALSE;
    }

public function getNews($id = 'ALL')
    {
        $id = sqlite_escape_string($id);

switch ($id) {
            case 'ALL':
                $sql = "SELECT id,
                               title
                        FROM   news
                        WHERE  approval = 'T'";
                break;
            case 'NEW':
                $sql = "SELECT *
                        FROM   news
                        WHERE  approval != 'T'";
                break;
            default:
                $sql = "SELECT *
                        FROM   news
                        WHERE  id = '$id'";
                break;
        }

if ($result = $this->_db->query($sql)) {
            if ($result->numRows() != 1) {
                return $result->fetchAll();
            } else {
                return $result->fetch();
            }
        }

return FALSE;
    }
}

?>

(你可以用自己的解决方案随意替换这个类。这里只是为你提供一个完整示例的介绍,并非建议要这么实现。)

这个类的构造器需要SQLite数据库的完整路径和文件名,你必须自己进行创建。

<?php

$db = new SQLiteDatabase('/path/to/db.sqlite');

$db->query("CREATE TABLE news (
                id       INTEGER PRIMARY KEY,
                title    VARCHAR(255),
                content  TEXT,
                approval CHAR(1) DEFAULT 'F'
            )");

$db->query("CREATE TABLE comments (
                id       INTEGER PRIMARY KEY,
                name     VARCHAR(255),
                comment  TEXT,
                newsId   INTEGER
            )");

?>

你只需要做一次,以后直接给出Database类构造器的完整路径和文件名即可:

<?php

$db = new Database('/path/to/db.sqlite');

?>

整合

为了进行整合,在lib目录下创建Database.phploadClass()就可以找到它。你的index.php文件现在就会初始化$view$db并存储到寄存器。你也可以创建__autoload()函数自动加载你所需要的类:

<?php

include 'Zend.php';

function __autoload($class)
{
    Zend::loadClass($class);
}

$db = new Database('/path/to/db.sqlite');
Zend::register('db', $db);

$view = new Zend_View;
$view->setScriptPath('/path/to/views');
Zend::register('view', $view);

$controller = Zend_Controller_Front::getInstance()
              ->setControllerDirectory('/path/to/controllers')
              ->dispatch();

?>

接下来,在views目录创建一些简单的模板。index.php可以用来显示index视图:

<html>
<head>
  <title>News</title>
</head>
<body>
  <h1>News</h1>
  <?php foreach ($this->news as $entry) { ?>
  <p>
    <a href="/view/<?php echo $this->escape($entry['id']); ?>">
    <?php echo $this->escape($entry['title']); ?>
    </a>
  </p>
  <?php } ?>
  <h1>Add News</h1>
  <form action="/add/news" method="POST">
  <p>Title:<br /><input type="text" name="title" /></p>
  <p>Content:<br /><textarea name="content"></textarea></p>
  <p><input type="submit" value="Add News" /></p>
  </form>
</body>
</html>

view.php模板可以用来显示选定的新闻条目:

<html>
<head>
  <title>
    <?php echo $this->escape($this->news['title']); ?>
  </title>
</head>
<body>
  <h1>
    <?php echo $this->escape($this->news['title']); ?>
  </h1>
  <p>
    <?php echo $this->escape($this->news['content']); ?>
  </p>
  <h1>Comments</h1>
  <?php foreach ($this->comments as $comment) { ?>
  <p>
    <?php echo $this->escape($comment['name']); ?> writes:
  </p>
  <blockquote>
    <?php echo $this->escape($comment['comment']); ?>
  </blockquote>
  <?php } ?>
  <h1>Add a Comment</h1>
  <form action="/add/comment" method="POST">
  <input type="hidden" name="newsId" 
    value="<?php echo $this->escape($this->id); ?>" />
  <p>Name:<br /><input type="text" name="name" /></p>
  <p>Comment:<br /><textarea name="comment"></textarea></p>
  <p><input type="submit" value="Add Comment" /></p>
  </form>
</body>
</html>

最后,admin.php模板可以用来批准新闻条目:

<html>
<head>
  <title>News Admin</title>
</head>
<body>
  <form action="/admin/approve" method="POST">
  <?php foreach ($this->news as $entry) { ?>
  <p>
    <input type="checkbox" name="ids[]"
    value="<?php echo $this->escape($entry['id']); ?>" />
    <?php echo $this->escape($entry['title']); ?>
    <?php echo $this->escape($entry['content']); ?>
  </p>
  <?php } ?>
  <p>
    Password:<br /><input type="password" name="password" />
  </p>
  <p><input type="submit" value="Approve" /></p>
  </form>
</body>
</html>
提示:为了保持简单,这个表单用密码作为验证机制。

使用到模板的地方,你只需要把注释替换成几行代码。如IndexController.php就变成下面这样:

<?php

class IndexController extends Zend_Controller_Action 
{
    public function indexAction()
    {
        /* List the news. */
        $db = Zend::registry('db');
        $view = Zend::registry('view');
        $view->news = $db->getNews();
        echo $view->render('index.php');
    }

public function noRouteAction()
    {
        $this->_redirect('/');
    }
}

?>

因为条理比较清楚,这个程序首页的整个业务逻辑只有四行代码。AddController.php更复杂一点,它需要更多的代码:

<?php

class AddController extends Zend_Controller_Action
{
    function indexAction()
    {
        $this->_redirect('/');
    }

function commentAction()
    {
        /* Add a comment. */
        $filterPost = new Zend_InputFilter($_POST);
        $db = Zend::registry('db');
        $name = $filterPost->getAlpha('name');
        $comment = $filterPost->noTags('comment');
        $newsId = $filterPost->getDigits('newsId');
        $db->addComment($name, $comment, $newsId);
        $this->_redirect("/view/$newsId");
    }

function newsAction()
    {
        /* Add news. */
        $filterPost = new Zend_InputFilter($_POST);
        $db = Zend::registry('db');
        $title = $filterPost->noTags('title');
        $content = $filterPost->noTags('content');
        $db->addNews($title, $content);
        $this->_redirect('/');
    }

function __call($action, $arguments)
    {
        $this->_redirect('/');
    }
}

?>

因为用户在提交表单后被重定向,这个controller不需要视图。

AdminController.php,你要处理显示管理界面和批准新闻两个action:

<?php

class AdminController extends Zend_Controller_Action
{
    function indexAction()
    {
        /* Display admin interface. */
        $db = Zend::registry('db');
        $view = Zend::registry('view');
        $view->news = $db->getNews('NEW');
        echo $view->render('admin.php');
    }

function approveAction()
    {
        /* Approve news. */
        $filterPost = new Zend_InputFilter($_POST);
        $db = Zend::registry('db');
        if ($filterPost->getRaw('password') == 'mypass') {
            $db->approveNews($filterPost->getRaw('ids'));
            $this->_redirect('/');
        } else {
            echo 'The password is incorrect.';
        }
    }

function __call($action, $arguments)
    {
        $this->_redirect('/');
    }
}

?>

最后是ViewController.php

<?php

class ViewController extends Zend_Controller_Action
{
    function indexAction()
    {
        $this->_redirect('/');
    }

function __call($id, $arguments)
    {
        /* Display news and comments for $id. */
        $id = Zend_Filter::getDigits($id);
        $db = Zend::registry('db');
        $view = Zend::registry('view');
        $view->news = $db->getNews($id);
        $view->comments = $db->getComments($id);
        $view->id = $id;
        echo $view->render('view.php');
    }
}

?>

虽然很简单,但我们还是提供了一个功能较全的新闻和评论程序。最好的地方是由于有较好的设计,增加功能变得很简单。而且随着Zend Framework越来越成熟,只会变得更好。

zend framework相关推荐

  1. Zend Framework Mail通过网易免费邮箱发送邮件

    2019独角兽企业重金招聘Python工程师标准>>> 做为一个苦逼的个人站长,做一个小网站,本来愿意来看的人就不多,再弄一个不能找回密码的会员系统?基本上被判死刑了 .阿里云的短信 ...

  2. zend framework php编码规范,Zend Framework常用校验器详解

    本文实例讲述了Zend Framework常用校验器.分享给大家供大家参考,具体如下: Date日期校验器 代码:<?php require_once 'Zend/Validate/Date.p ...

  3. PHP高级教程——Zend Framework核心开发人员力作

    <PHP高级程序设计:模式.框架与测试> -- Zend Framework核心开发人员力作 在过去的十年间, PHP 已经从一套为 Web 站点开发人员提供的简单工具转化成完整的 OOP ...

  4. Zend Framework 2 中,定制error 的layout

    为什么80%的码农都做不了架构师?>>>    404页面在我们平常浏览网页的时候并不会经常碰到,也因此很容易被忽略,在Zend Framework 2中,项目的结构已经默认提供了4 ...

  5. Zend Framework中,执行自定义sql语句

    Zend Framework中的Zend_Db_Table类可以很好的对数据表实现select,insert,delete等操作.但是有时候还是希望自己运行一些sql语句. ZF当然也是支持的. 一种 ...

  6. Zend Framework一

    很久没有写东西了,有点懒了.最近做了一个PHP的项目,使用的框架是Zend Framework 1.8.第一次做PHP的项目,也是第一次使用Zend Framework.在网上找它的教程,发现中文教程 ...

  7. php zend框架入门,Zend Framework 入门——快速上手

    1. 安装 从 Zend Framework 的网页上下载最新版本.解压后,把整个目录拷贝到一个理想的地方,比如:/php/library/Zend. 打开 php.ini 文件,确认包含 Zend ...

  8. zend framework mysql_Zend Framework连接Mysql数据库实例分析

    这篇文章主要介绍了Zend Framework连接Mysql数据库的方法,以完整实例形式分析了Zend Framework连接MySQL数据库的具体步骤与相关实现技巧,需要的朋友可以参考下 本文实例讲 ...

  9. Zend Framework 的 PHP 编码标准

    C.2. PHP File 文件格式 C.2.1.  常规 对于只包含有 PHP 代码的文件,结束标志("?>")是不允许存在的,PHP自身不需要("?>&q ...

  10. Zend framework重定向的方法

    zend framework重定向的方法有三种.render, forward, redirect.它们各自的用法是什么样子的呢?有什么区别呢? 一.render render是用来调视图用的,不会调 ...

最新文章

  1. 全球奖金最高的科学奖项颁发:黑洞拍摄团队、肥胖症治疗等获奖;2位清华北大校友入围...
  2. tomcat android https,tomcat 配置 https, android端 访问
  3. 20160808_安装JDK7u79
  4. 后台获取(Background Fetch) - HTTP 203 Advent
  5. java数据源是什么_《java数据源—连接池》
  6. 前端学习(1853)vue之电商管理系统电商系统之git安装
  7. Mysql学习总结(49)——从开发规范、选型、拆分到减压
  8. 收购小蓝单车部分资产、与ofo蜜月期结束,滴滴重构共享单车布局
  9. 3、JSON相关基础知识点总结(3)
  10. vuex模块化 怎么引用state_vue 组件如何调用 vuex 模块中的getters
  11. 平面设计论文要如何写?
  12. 用HTML5做一个个人网站,此文仅展示个人主页界面。内附源代码下载地址
  13. vue3图片对比组件
  14. 用移动硬盘当系统盘,即插即用
  15. win10下ipv6安装与设置
  16. 统计局解读1月制造业采购经理指数:服务业回升明显
  17. 分享大神的一些博文、视频、资料--持续更新
  18. 柯洁夺斗地主全国冠军!斗地主可以排解输棋痛苦”
  19. 开关电源buck电感、电容选择
  20. 基于单片机的模拟风扇控制系统

热门文章

  1. 阿秀现身揭秘抖音内部最常用的编程语言学习方法
  2. 华为鸿蒙OS2.0:为中国的软件行业种“根”
  3. 非接触式IC卡、条码卡、磁道卡、接触式IC卡、芯片卡
  4. 使用WinPE安装Windows 7——思齐博客
  5. 钢筋混凝土和预应力钢筋混凝土的区别
  6. 万邦阿里巴巴中国站获得1688商品详情 API 返回值说明
  7. (转)为什么BAT干不掉海康威视?——关于人工智能的思考
  8. PNA肽核酸修饰多肽Pro-Phe-Arg-pNA (S-2302)|Dnp-Gly-X-L-Pro-Gly-pNA
  9. HRM人力资源系统-Day11
  10. 目标检测算法回顾之发展概览