溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Zend Framework開發(fā)入門的示例分析

發(fā)布時間:2021-09-02 09:30:22 來源:億速云 閱讀:133 作者:小新 欄目:開發(fā)技術

這篇文章主要介紹了Zend Framework開發(fā)入門的示例分析,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

具體如下:

Zend Framework發(fā)布了!雖然仍處于開發(fā)初期,這個教程仍突出講解目前幾個最好的功能,并指導你完成一個簡單程序的構建。

Zend最早在社區(qū)里發(fā)布了ZF?;谕瑯拥南敕?,這個教程寫來用于展示ZF現(xiàn)有的功能。由于這個教程是在線發(fā)布,我將在ZF變化時對其進行更新,以便盡可能有效。

要求

Zend Framework要求PHP5。為了更好利用本教程的代碼,你還需要Apache網(wǎng)頁服務器。因為示范程序(一個新聞管理系統(tǒng))用到了mod_rewrite。

這個教程的代碼可以自由下載,所以你可以自己試一下。你可以從Brain Buld的網(wǎng)站下載到代碼:http://brainbulb.com/zend-framework-tutorial.tar.gz。

下載ZF

當你開始這篇教程時,你需要下載ZF的最新版本。你可以用瀏覽器手工從http://framework.zend.com/download選擇tar.gz或zip文件進行下載,或者使用下列命令:

$ 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目錄是文檔根目錄,controllers和views目錄是以后會用到的空目錄,而lib目錄來自你下載的預覽版。

開始

我要介紹的第一個組件是Zend_Controller。從很多方面看,它為你開發(fā)的程序提供了基礎,同時也部分決定了Zend Framework不只是個組件的集合。但是,你在用之前需要將所有的得到的請求都放到一個簡單的PHP腳本。本教程用的是mod_rewrite。

用mod_rewrite自身是一種藝術,但幸運的是,這個特殊的任務特別簡單。如果你對mod_rewrite或Apache的一般配置不熟悉,在文檔根目錄下創(chuàng)建一個.htaccess文件,并添加以下內容:

RewriteEngine on
RewriteRule !/.(js|ico|gif|jpg|png|css)$ index.php

提示: Zend_Controller的一個TODO項目就是取消對mod_rewrite的依賴。為了提供一個預覽版的范例,本教程用了mod_rewrite。

如果你直接把這些內容添加到httpd.conf,你必須重啟網(wǎng)頁服務器。但如果你用.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類包含了一些經(jīng)常使用的靜態(tài)方法的集合。下面是唯一一個你要手工添加的類:

<?php
include 'Zend.php';
?>

一旦你包含了Zend.php,你就已經(jīng)包含了Zend類的所有的類方法。用loadClass()就可以簡單地加載其它類。例如,加載Zend_Controller_Front類:

<?php
include 'Zend.php';
Zend::loadClass('Zend_Controller_Front');
?>

include_path能理解loadclass()及ZF的組織和目錄結構。我用它加載所有其它類。  

Zend_Controller

使用這個controller非常直觀。事實上,我寫本教程時并沒有用到它豐富的文檔。

提示:文檔目前已經(jīng)可以在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();
?>

現(xiàn)在如果你訪問/foo/bar,會有錯誤發(fā)生。沒錯!它讓你知道發(fā)生了什么事。主要的問題是找不到IndexController.php文件。

在你創(chuàng)建這個文件之前,應先理解一下ZF想讓你怎樣組織這些事情。ZF把訪問請求給拆分開來。假如訪問的是/foo/bar,則foo是controller,而bar是action。它們的默認值都是index.

如果foo是controller,ZF就會去查找controllers目錄下的FooController.php文件。因為這個文件不存在,ZF就退回到IndexController.php。結果都沒有找到,就報錯了。

接下來,在controllers目錄創(chuàng)建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/index,indexAction()方法就會被執(zhí)行。 (最后面的斜杠并不會改變這個行為。) 而訪問其他任何資源只會導致出錯。

在繼續(xù)做之前,還要在IndexController加上另外一個有用的類方法。不管什么時候訪問一個不存在的控制器,都要調用noRouteAction()類方法。例如,在FooController.php不存在的條件下,訪問/foo/bar就會執(zhí)行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('/')來描述執(zhí)行noRouteAction()時,可能發(fā)生的行為。這會將對不存在controllers的訪問重定向到根文檔(首頁)。

現(xiàn)在創(chuàng)建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,你會發(fā)現(xiàn)執(zhí)行了barAction(),因為bar是action?,F(xiàn)在你不只支持了友好的URL,還可以只用幾行代碼就做得這么有條理??岚桑?br/>你也可以創(chuàng)建一個__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()';
  }
}
?>

現(xiàn)在你只要幾行代碼就可以很好地處理用戶的訪問了,準備好繼續(xù)。

Zend_View

Zend_View是一個用來幫助你組織好你的view邏輯的類。這對于模板-系統(tǒng)是不可知的,為了簡單起見,本教程不使用模板。如果你喜歡的話,不妨用一下。

記住,現(xiàn)在所有的訪問都是由front controller進行處理。因此應用框架已經(jīng)存在了,另外也必須遵守它。為了展示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目錄創(chuàng)建example.php文件:

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

現(xiàn)在,如果你訪問自己網(wǎng)站的根資源,你會看到example.php的內容。這仍沒什么用,但你要清楚你要在以一種結構和組織非常清楚的方式在開發(fā)網(wǎng)絡應用。

為了讓Zend_View的應用更清楚一點,,修改你的模板(example.php)包含以下內容:

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

現(xiàn)在已經(jīng)添加了兩個功能。$this->escape()類方法用于所有的輸出。即使你自己創(chuàng)建輸出,就像這個例子一樣。避開所有輸出也是一個很好的習慣,它可以在默認情況下幫助你防止跨站腳本攻擊(XSS)。

$this->title和$this->body屬性用來展示動態(tài)數(shù)據(jù)。這些也可以在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('/');
  }
}
?>

現(xiàn)在你再次訪問根目錄,應該就可以看到模板所使用的這些值了。因為你在模板中使用的$this就是在Zend_View范圍內所執(zhí)行的實例。

要記住example.php只是一個普通的PHP腳本,所以你完全可以做你想做的。只是應努力只在要求顯示數(shù)據(jù)時才使用模板。你的controller (controller分發(fā)的模塊)應處理你全部的業(yè)務邏輯。

在繼續(xù)之前,我想做最后一個關于Zend_View的提示。在controller的每個類方法內初始化$view對象需要額外輸入一些內容,而我們的主要目標是讓快速開發(fā)網(wǎng)絡應用更簡單。如果所有模板都放在一個目錄下,是否要在每個例子中都調用setScriptPath()也存在爭議。

幸運的是,Zend類包含了一個寄存器來幫助減少工作量。你可以用register()方法把你的$view對象存儲在寄存器:

<?php
Zend::register('view', $view);
?>

用registry()方法進行檢索:

<?php
$view = Zend::registry('view');
?>

基于這點,本教程使用寄存器。 

Zend_InputFilter

本教程討論的最后一個組件是Zend_InputFilter。這個類提供了一種簡單而有效的輸入過濾方法。你可以通過提供一組待過濾數(shù)據(jù)來進行初始化。

<?php
$filterPost = new Zend_InputFilter($_POST);
?>

這會將($_POST)設置為NULL,所以就不能直接進入了。Zend_InputFilter提供了一個簡單、集中的根據(jù)特定規(guī)則過濾數(shù)據(jù)的類方法集。例如,你可以用getAlpha()來獲取$_POST['name']中的字母:

<?php
/* $_POST['name'] = 'John123Doe'; */
$filterPost = new Zend_InputFilter($_POST);
/* $_POST = NULL; */
$alphaName = $filterPost->getAlpha('name');
/* $alphaName = 'JohnDoe'; */
?>

每一個類方法的參數(shù)都是對應要過濾的元素的關鍵詞。對象(例子中的$filterPost)可以保護數(shù)據(jù)不被篡改,并能更好地控制對數(shù)據(jù)的操作及一致性。因此,當你操縱輸入數(shù)據(jù),應始終使用Zend_InputFilter。

提示:Zend_Filter提供與Zend_InputFilter方法一樣的靜態(tài)方法。

構建新聞管理系統(tǒng)

雖然預覽版提供了許多組件(甚至許多已經(jīng)被開發(fā)),我們已經(jīng)討論了構建一個簡單程序所需要的全部組件。在這里,你會對ZF的基本結構和設計有更清楚的理解。

每個人開發(fā)的程序都會有所不同,而Zend Framework試圖包容這些差異。同樣,這個教程是根據(jù)我的喜好寫的,請根據(jù)自己的偏好自行調整。

當我開發(fā)程序時,我會先做界面。這并不意味著我把時間都花在標簽、樣式表和圖片上,而是我從一個用戶的角度去考慮問題。因此我把程序看成是頁面的集合,每一頁都是一個獨立的網(wǎng)址。這個新聞系統(tǒng)就是由以下網(wǎng)址組成的:

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

你可以直接把這些網(wǎng)址和controller聯(lián)系起來。IndexController列出新聞,AddController添加新聞和評論,AdminController處理一些如批準新聞之類的管理,ViewController特定新聞和對應評論的顯示。

如果你的FooController.php還在,把它刪除。修改IndexController.php,為業(yè)務邏輯以添加相應的action和一些注釋:

<?php
Zend::loadClass('Zend_Controller_Action');
class IndexController extends Zend_Controller_Action 
{
  public function indexAction()
  {
    /* List the news. */
  }
  public function noRouteAction()
  {
    $this->_redirect('/');
  }
}
?>

接下來,創(chuàng)建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('/');
  }
}
?>

記住AddController的indexAction()方法不能調用。當訪問/add時會執(zhí)行這個類方法。因為用戶可以手工訪問這個網(wǎng)址,這是有可能的,所以你要把用戶重定向到主頁、顯示錯誤或你認為合適的行為。

接下來,創(chuàng)建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('/');
  }
}
?>

最后,創(chuàng)建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這樣的網(wǎng)址,你要使用__call()來支持動態(tài)action。

數(shù)據(jù)庫操作

因為Zend Framework的數(shù)據(jù)庫組件還不穩(wěn)定,而我希望這個演示可以做得簡單一點。我使用了一個簡單的類,用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;
  }
}
?>

(你可以用自己的解決方案隨意替換這個類。這里只是為你提供一個完整示例的介紹,并非建議要這么實現(xiàn)。)

這個類的構造器需要SQLite數(shù)據(jù)庫的完整路徑和文件名,你必須自己進行創(chuàng)建。

<?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目錄下創(chuàng)建Database.php,loadClass()就可以找到它。你的index.php文件現(xiàn)在就會初始化$view和$db并存儲到寄存器。你也可以創(chuàng)建__autoload()函數(shù)自動加載你所需要的類:

<?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目錄創(chuàng)建一些簡單的模板。index.php可以用來顯示index視圖:

<html>
<head>
 <title>News</title>
</head>
<body>
 <h2>News</h2>
 <?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 } ?>
 <h2>Add News</h2>
 <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>
 <h2>
  <?php echo $this->escape($this->news['title']); ?>
 </h2>
 <p>
  <?php echo $this->escape($this->news['content']); ?>
 </p>
 <h2>Comments</h2>
 <?php foreach ($this->comments as $comment) { ?>
 <p>
  <?php echo $this->escape($comment['name']); ?> writes:
 </p>
 <blockquote>
  <?php echo $this->escape($comment['comment']); ?>
 </blockquote>
 <?php } ?>
 <h2>Add a Comment</h2>
 <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('/');
  }
}
?>

因為條理比較清楚,這個程序首頁的整個業(yè)務邏輯只有四行代碼。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開發(fā)入門的示例分析”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業(yè)資訊頻道,更多相關知識等著你來學習!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內容。

AI