Zend Framework 2-介紹 Service 和 ServiceManager

2018-09-28 20:19 更新

介紹 Service 和 ServiceManager

在上一個(gè)章節(jié)中我們已經(jīng)學(xué)習(xí)了如何在 Zend Framework 2 中創(chuàng)建一個(gè)簡(jiǎn)單的“Hello World”應(yīng)用程序。這是一個(gè)良好易學(xué)的開端,但是應(yīng)用程序本身并沒實(shí)現(xiàn)任何事情。在這個(gè)章節(jié)我們會(huì)將 Service(服務(wù))的概念介紹給您,通過這篇關(guān)于 Zend\ServiceManager\ServiceManager 的簡(jiǎn)介文章。

什么是 Service

一個(gè) Service 是一個(gè)執(zhí)行復(fù)雜應(yīng)用程序邏輯的對(duì)象。它是應(yīng)用程序的一個(gè)組成部分,處理所有復(fù)雜的事物并且返回一個(gè)簡(jiǎn)單易懂的結(jié)果給您。

為了完成我們想讓 Blog 模塊完成的事情,需要?jiǎng)?chuàng)建一個(gè) Service 來讓它返回我們所需的數(shù)據(jù)。該 Service 會(huì)從某些源獲得數(shù)據(jù),然而當(dāng)我們編寫 Service 時(shí)并不會(huì)真的在意數(shù)據(jù)源是什么。Service 會(huì)根據(jù)一個(gè)我們定義的 Interface 來編寫,而未來的數(shù)據(jù)提供者也要根據(jù)這個(gè)接口來實(shí)現(xiàn)。

編寫 PostService

當(dāng)編寫一個(gè) Service 的時(shí)候,事先定義 Interface 是一項(xiàng)常見的最佳實(shí)踐。定義 Interface 可以很好的確保其他程序員能夠方便地為我們的服務(wù)編寫擴(kuò)展,通過他們自己的實(shí)現(xiàn)方法。換句話說,他們可以編寫擁有完全一樣的函數(shù)名的 Service,內(nèi)部實(shí)現(xiàn)方法完全不同,但是擁有一樣的特定的輸出。

在我們這個(gè)例子中,我們需要?jiǎng)?chuàng)建一個(gè) PostService。這意味著首先我們要定義一個(gè) PostServiceInterface。我們的 Service 的任務(wù)是將博客帖子的數(shù)據(jù)提供給我們。目前我們先將焦點(diǎn)放在只讀類型的任務(wù)。想定義一個(gè)函數(shù)來讓我們獲取所有帖子的列表,然后我們?cè)俣x一個(gè)函數(shù)來獲取單個(gè)帖子的內(nèi)容。

首先我們先在 /module/Blog/src/Blog/Service/PostServiceInterface.php 內(nèi)定義接口。

<?php
 // 文件名: /module/Blog/src/Blog/Service/PostServiceInterface.php
 namespace Blog\Service;

 use Blog\Model\PostInterface;

 interface PostServiceInterface
 {
     /**
      * 應(yīng)該會(huì)分會(huì)所有博客帖子集,以便我們對(duì)其遍歷。數(shù)組中的每個(gè)條目應(yīng)該都是
      * \Blog\Model\PostInterface 接口的實(shí)現(xiàn)
      *
      * @return array|PostInterface[]
      */
     public function findAllPosts();

     /**
      * 應(yīng)該會(huì)返回單個(gè)博客帖子
      *
      * @param  int $id 應(yīng)該被返回的帖子的標(biāo)識(shí)符
      * @return PostInterface
      */
     public function findPost($id);
 }

如您所見我們定義了兩個(gè)函數(shù)。第一個(gè)是 findAllPosts() 用來返回所有的帖子,而第二個(gè)函數(shù)是 findPost($id) 用來返回和 $id 標(biāo)識(shí)符參數(shù)匹配的帖子。新奇的是事實(shí)上我們定義了一個(gè)返回值,然而該值還不存在。我們已經(jīng)默認(rèn)返回值基本都是 Blog\Model\PostInterface 類型。我們會(huì)在稍后定義這個(gè)類,目前先創(chuàng)建 PostService。

/module/Blog/src/Blog/Service/PostService.php 內(nèi)創(chuàng)建類 PostService,請(qǐng)確保實(shí)現(xiàn) PostServiceInterface 和它所依賴的函數(shù)(我們會(huì)稍后補(bǔ)全這些函數(shù))。然后您應(yīng)該有一個(gè)類看上去如同下文:

 <?php
 // 文件名: /module/Blog/src/Blog/Service/PostService.php
 namespace Blog\Service;

 class PostService implements PostServiceInterface
 {
     /**
      * {@inheritDoc}
      */
     public function findAllPosts()
     {
         // 文件名: TODO: Implement findAllPosts() method.
     }

     /**
      * {@inheritDoc}
      */
     public function findPost($id)
     {
         // 文件名: TODO: Implement findPost() method.
     }
 }

編寫所需的 Model 文件

因?yàn)槲覀兊?PostService 會(huì)返回 Model,所以也要?jiǎng)?chuàng)建它們。請(qǐng)確保先為 Model 編寫 Interface!我們來創(chuàng)建 /module/Blog/src/Blog/Model/PostInterface.php/module/Blog/src/Blog/Model/Post.php。首先是 /module/Blog/src/Blog/Model/Post.php

 <?php
 // 文件名: /module/Blog/src/Blog/Model/PostInterface.php
 namespace Blog\Model;

 interface PostInterface
 {
     /**
      * 會(huì)返回博客帖子的 ID
      *
      * @return int
      */
     public function getId();

     /**
      * 會(huì)返回博客帖子的標(biāo)題
      *
      * @return string
      */
     public function getTitle();

     /**
      * 會(huì)返回博客帖子的文本
      *
      * @return string
      */
     public function getText();
 }

請(qǐng)注意我們?cè)谶@里只創(chuàng)造了 getter 函數(shù)。這是因?yàn)槲覀兡壳安魂P(guān)心數(shù)據(jù)是如何進(jìn)入 Post 類,我們只關(guān)心我們?nèi)绾文芡ㄟ^這些 getter 函數(shù)訪問這些屬性。

然后現(xiàn)在我們對(duì)照接口創(chuàng)建合適的 Model 文件。請(qǐng)確保設(shè)置所需的類屬性并且補(bǔ)全我們的 PostInterface 接口定義的 getter 函數(shù)。盡管我們的接口不關(guān)心 setter 函數(shù),我們還是編寫相應(yīng)的函數(shù)來讓我們的測(cè)試數(shù)據(jù)得以寫入。然后您應(yīng)該有一個(gè)類類似下文:

 <?php
 // 文件名: /module/Blog/src/Blog/Model/Post.php
 namespace Blog\Model;

 class Post implements PostInterface
 {
     /**
      * @var int
      */
     protected $id;

     /**
      * @var string
      */
     protected $title;

     /**
      * @var string
      */
     protected $text;

     /**
      * {@inheritDoc}
      */
     public function getId()
     {
         return $this->id;
     }

     /**
      * @param int $id
      */
     public function setId($id)
     {
         $this->id = $id;
     }

     /**
      * {@inheritDoc}
      */
     public function getTitle()
     {
         return $this->title;
     }

     /**
      * @param string $title
      */
     public function setTitle($title)
     {
         $this->title = $title;
     }

     /**
      * {@inheritDoc}
      */
     public function getText()
     {
         return $this->text;
     }

     /**
      * @param string $text
      */
     public function setText($text)
     {
         $this->text = $text;
     }
 }

為我們的 PostService 賦予生機(jī)

現(xiàn)在我們擁有我們所需的 Model 文件,可以為 PostService 類賦予生機(jī)了。為了讓 Service 層清晰易懂,我們目前只會(huì)讓 PostService 直接返回一些事先寫死的(硬編碼的)內(nèi)容。在 PostService 內(nèi)創(chuàng)建一個(gè)名為 $data 的屬性,并將其定義為我們的 Model 類型數(shù)組。如下例編輯 PostService

 <?php
 // 文件名: /module/Blog/src/Blog/Service/PostService.php
 namespace Blog\Service;

 class PostService implements PostServiceInterface
 {
     protected $data = array(
         array(
             'id'    => 1,
             'title' => 'Hello World #1',
             'text'  => 'This is our first blog post!'
         ),
         array(
             'id'     => 2,
             'title' => 'Hello World #2',
             'text'  => 'This is our second blog post!'
         ),
         array(
             'id'     => 3,
             'title' => 'Hello World #3',
             'text'  => 'This is our third blog post!'
         ),
         array(
             'id'     => 4,
             'title' => 'Hello World #4',
             'text'  => 'This is our fourth blog post!'
         ),
         array(
             'id'     => 5,
             'title' => 'Hello World #5',
             'text'  => 'This is our fifth blog post!'
         )
     );

     /**
      * {@inheritDoc}
      */
     public function findAllPosts()
     {
         // 文件名: TODO: Implement findAllPosts() method.
     }

     /**
      * {@inheritDoc}
      */
     public function findPost($id)
     {
         // 文件名: TODO: Implement findPost() method.
     }
 }

我們現(xiàn)在有一些數(shù)據(jù)了,來修改 find*() 函數(shù)來使其返回合適的 Model 文件:

 <?php
 // 文件名: /module/Blog/src/Blog/Service/PostService.php
 namespace Blog\Service;

 use Blog\Model\Post;

 class PostService implements PostServiceInterface
 {
     protected $data = array(
         array(
             'id'    => 1,
             'title' => 'Hello World #1',
             'text'  => 'This is our first blog post!'
         ),
         array(
             'id'     => 2,
             'title' => 'Hello World #2',
             'text'  => 'This is our second blog post!'
         ),
         array(
             'id'     => 3,
             'title' => 'Hello World #3',
             'text'  => 'This is our third blog post!'
         ),
         array(
             'id'     => 4,
             'title' => 'Hello World #4',
             'text'  => 'This is our fourth blog post!'
         ),
         array(
             'id'     => 5,
             'title' => 'Hello World #5',
             'text'  => 'This is our fifth blog post!'
         )
     );

     /**
      * {@inheritDoc}
      */
     public function findAllPosts()
     {
         $allPosts = array();

         foreach ($this->data as $index => $post) {
             $allPosts[] = $this->findPost($index);
         }

         return $allPosts;
     }

     /**
      * {@inheritDoc}
      */
     public function findPost($id)
     {
         $postData = $this->data[$id];

         $model = new Post();
         $model->setId($postData['id']);
         $model->setTitle($postData['title']);
         $model->setText($postData['text']);

         return $model;
     }
 }

如您所見,現(xiàn)在我們兩個(gè)函數(shù)都擁有合適的返回值了。請(qǐng)注意從技術(shù)角度而言目前的實(shí)現(xiàn)距離完美還有一大段距離,不過我們會(huì)在未來大幅度地改進(jìn)這個(gè) Service。至少我們目前擁有了一個(gè)能運(yùn)行的 Service 來給我們一些數(shù)據(jù),而這些數(shù)據(jù)吻合我們先前定義的 PostServiceInterface 接口。

將 Service 帶進(jìn) Controller

現(xiàn)在我們寫好了 PostService,接下來就想在我們的 Controller(控制器) 內(nèi)訪問這個(gè) Service。為了實(shí)現(xiàn)這點(diǎn)我們即將帶出一個(gè)新主題,稱為“Dependency Injection”(依賴對(duì)象注入),簡(jiǎn)稱“DI”。

當(dāng)我們談?wù)撘蕾囮P(guān)系注入的時(shí)候,其實(shí)就是在談如何為類設(shè)置依賴對(duì)象的問題。最常見的形式,“Constructor Injection”(構(gòu)造器注入),就是用于指定該類全時(shí)需要的所有依賴對(duì)象的一種方法。

在這個(gè)例子中,我們想讓博客模組 ListController 和我們的 PostService 互動(dòng)。這意味著 PostService 類是類 ListController 的一個(gè)依賴對(duì)象(ListController 依賴 PostService),沒有了 PostService,ListController也無法正常運(yùn)作。為了確保 ListController 總能得到相應(yīng)的依賴對(duì)象,我們會(huì)在 ListController 的構(gòu)造器 __construct() 中事先定義好依賴對(duì)象。請(qǐng)將 ListController 修改成下例所示:

<?php
 // 文件名: /module/Blog/src/Blog/Controller/ListController.php
 namespace Blog\Controller;

 use Blog\Service\PostServiceInterface;
 use Zend\Mvc\Controller\AbstractActionController;

 class ListController extends AbstractActionController
 {
     /**
      * @var \Blog\Service\PostServiceInterface
      */
     protected $postService;

     public function __construct(PostServiceInterface $postService)
     {
         $this->postService = $postService;
     }
 }

如您所見,我們的 __construct() 函數(shù)現(xiàn)在有了一個(gè)必要的參數(shù)?,F(xiàn)在再也不能沒有將符合 PostserviceInterface 接口的類實(shí)例作為參數(shù)傳遞的情況下調(diào)用這個(gè)類了。如果你現(xiàn)在返回瀏覽器并通過 URL localhost:8080/blog 重新載入您的工程,下面的錯(cuò)誤信息將映入您的眼簾:

 ( ! ) Catchable fatal error: Argument 1 passed to Blog\Controller\ListController::__construct()
       must be an instance of Blog\Service\PostServiceInterface, none given,
       called in {libraryPath}\Zend\ServiceManager\AbstractPluginManager.php on line {lineNumber}
       and defined in \module\Blog\src\Blog\Controller\ListController.php on line 15

這個(gè)錯(cuò)誤是預(yù)料之中的,它告訴你我們的 ListController 期望接收 PostServiceInterface 接口的一個(gè)實(shí)現(xiàn)作為參數(shù)。

那么我們?nèi)绾未_保 ListController 會(huì)接收到這樣的一個(gè)實(shí)現(xiàn)?解決問題之道在于告訴應(yīng)用程序如何創(chuàng)建 Blog\Controller\ListController 的實(shí)例。如果你還記得我們?nèi)绾蝿?chuàng)造控制器的話,類似的,在模組配置文件中的 invokable 數(shù)組中添加一個(gè)條目:

<?php
 // 文件名: /module/Blog/config/module.config.php
 return array(
     'view_manager' => array( /** ViewManager Config */ ),
     'controllers'  => array(
         'invokables' => array(
             'Blog\Controller\List' => 'Blog\Controller\ListController'
         )
     ),
     'router' => array( /** Router Config */ )
 );

一個(gè) invokable 類是一個(gè)可以在沒有任何參數(shù)下構(gòu)造的類。由于我們的 Blog\Controller\ListController 現(xiàn)在需要有構(gòu)造參數(shù)了,所以需要對(duì)此進(jìn)行一點(diǎn)連帶修改。ControllerManager 負(fù)責(zé)實(shí)例化控制器,也支持使用 factories。factory 類用于創(chuàng)建其他類的實(shí)例?,F(xiàn)在我們?yōu)槲覀兊?ListController 創(chuàng)建一個(gè) factory 類,先將我們的配置文件按照下例修改:

 <?php
 // 文件名: /module/Blog/config/module.config.php
 return array(
     'view_manager' => array( /** ViewManager Config */ ),
     'controllers'  => array(
         'factories' => array(
             'Blog\Controller\List' => 'Blog\Factory\ListControllerFactory'
         )
     ),
     'router' => array( /** Router Config */ )
 );

如您所見,再也沒有 invokable 鍵了,取而代之的是 factories 鍵。并且,我們的控制器名稱 Blog\Controller\List 已經(jīng)被改成不直接匹配 Blog\Controller\ListController 類,而是調(diào)用一個(gè)叫做 Blog\Factory\ListControllerFactory 的類。此時(shí)如果你刷新瀏覽器,你會(huì)看見另外一個(gè)錯(cuò)誤信息:

 An error occurred
 An error occurred during execution; please try again later.

 Additional information:
 Zend\ServiceManager\Exception\ServiceNotCreatedException

 File:
 {libraryPath}\Zend\ServiceManager\AbstractPluginManager.php:{lineNumber}

 Message:
 While attempting to create blogcontrollerlist(alias: Blog\Controller\List) an invalid factory was registered for this instance type.

這個(gè)信息應(yīng)該相對(duì)容易理解。Zend\Mvc\Controller\ControllerManager 正在訪問 Blog\Controller\List,其內(nèi)部表示是 blogcontrollerlist。當(dāng)它試圖執(zhí)行這個(gè)操作的時(shí)候發(fā)現(xiàn)要調(diào)用這個(gè)控制器,需要先調(diào)用一個(gè) factory 類,然而它并不能找到這個(gè) factory 類,所以產(chǎn)生了我們剛才看見的錯(cuò)誤。這也是理所當(dāng)然的,畢竟我們還沒有寫 factory 類,所以接下來我們來干這件事。

編寫一個(gè) Factory 類

在 Zend Framework 2 中的 Factory 類總是需要實(shí)現(xiàn) Zend\ServiceManager\FactoryInterface 接口。實(shí)現(xiàn)這個(gè)類可以讓 ServiceManager 知道函數(shù) createService() 應(yīng)該被調(diào)用。并且 createService() 其實(shí)期望接收一個(gè) ServiceLocatorInterface 的實(shí)現(xiàn)作為參數(shù),這樣 ServiceManager 就可以通過先前提到的依賴對(duì)象注入來對(duì)該參數(shù)進(jìn)行注入了。首先我們來實(shí)現(xiàn) factory 類:

 <?php
 // 文件名: /module/Blog/src/Blog/Factory/ListControllerFactory.php
 namespace Blog\Factory;

 use Blog\Controller\ListController;
 use Zend\ServiceManager\FactoryInterface;
 use Zend\ServiceManager\ServiceLocatorInterface;

 class ListControllerFactory implements FactoryInterface
 {
     /**
      * Create service
      *
      * @param ServiceLocatorInterface $serviceLocator
      *
      * @return mixed
      */
     public function createService(ServiceLocatorInterface $serviceLocator)
     {
         $realServiceLocator = $serviceLocator->getServiceLocator();
         $postService        = $realServiceLocator->get('Blog\Service\PostServiceInterface');

         return new ListController($postService);
     }
 }

現(xiàn)在東西看起來好復(fù)雜!讓我們先來看看 $realServiceLocator。當(dāng)使用一個(gè) Factory 類 時(shí),其本身會(huì)被 ControllerManager 調(diào)用,事實(shí)上它會(huì)將自己$serviceLocator 名義進(jìn)行注入。然而我們需要真正的 ServiceManager 來訪問 Service 類,這就是為什么我們?nèi)フ{(diào)用 getServiceLocator() 函數(shù)來獲取真正的 ServiceManager

在我們?cè)O(shè)定好 $realServiceLocator(真正的 ServiceLocator) 之后,去嘗試獲得一個(gè)叫做 Blog\Service\PostServiceInterface 的 Service。該操作應(yīng)該會(huì)得到一個(gè)匹配 PostServiceInterface 的 Service,然后再將獲得的 Service 傳給 ListController,然后 ListController 再被返回。

請(qǐng)注意盡管我們還沒有注冊(cè)一個(gè)叫做 Blog\Service\PostServiceInterface 的 Service,也請(qǐng)不要期待有天上掉餡餅?zāi)菢幼詣?dòng)生成的好事發(fā)生,畢竟我們只是給了 Service 一個(gè)接口的名稱。刷新您的瀏覽器,然后就能看見下述錯(cuò)誤信息:

 An error occurred
 An error occurred during execution; please try again later.

 Additional information:
 Zend\ServiceManager\Exception\ServiceNotFoundException

 File:
 {libraryPath}\Zend\ServiceManager\ServiceManager.php:{lineNumber}

 Message:
 Zend\ServiceManager\ServiceManager::get was unable to fetch or create an instance for Blog\Service\PostServiceInterface

和我們預(yù)想的完全一致。應(yīng)用程序中的某處,目前是在我們的 factory 類,要求一個(gè)叫做 Blog\Service\PostServiceInterface 的 Service,但是卻還不認(rèn)識(shí)這個(gè) Service,所以沒有辦法創(chuàng)建被請(qǐng)求的實(shí)例。

注冊(cè) Service

注冊(cè)一個(gè) Service 和注冊(cè) Controller 一樣簡(jiǎn)單。我們只需要修改 module.config.php 文件,添加一個(gè)叫做 service_manager 新鍵,其也擁有 invokablefactories。和我們將兩者包含在 controllers 數(shù)組內(nèi)一樣,具體請(qǐng)參照下例配置文件:

 <?php
 // 文件名: /module/Blog/config/module.config.php
 return array(
     'service_manager' => array(
         'invokables' => array(
             'Blog\Service\PostServiceInterface' => 'Blog\Service\PostService'
         )
     ),
     'view_manager' => array( /** View Manager Config */ ),
     'controllers'  => array( /** Controller Config */ ),
     'router'       => array( /** Router Config */ )
 );

如您所見,現(xiàn)在我們添加了一個(gè)新的 Service 來監(jiān)聽名稱 Blog\Service\PostServiceInterface 并且指向我們自己的實(shí)現(xiàn)(Blog\Service\PostService)。由于我們的 Service 沒有任何依賴對(duì)象,所以我們能夠?qū)⑦@個(gè) Service 添加到 invokable 數(shù)組中。現(xiàn)在去試試打開瀏覽器并刷新頁(yè)面,你應(yīng)該看不到任何錯(cuò)誤信息了,而是和上一個(gè)教程一樣的頁(yè)面內(nèi)容。

在我們的 Controller 中使用 Service

現(xiàn)在讓我們?cè)?ListController 中使用 PostService。要實(shí)現(xiàn)這點(diǎn)我們需要復(fù)寫默認(rèn) indexAction() 函數(shù)并且將 PostService 的值返回到視圖。參照下例修改 ListController

 <?php
 // 文件名: /module/Blog/src/Blog/Controller/ListController.php
 namespace Blog\Controller;

 use Blog\Service\PostServiceInterface;
 use Zend\Mvc\Controller\AbstractActionController;
 use Zend\View\Model\ViewModel;

 class ListController extends AbstractActionController
 {
     /**
      * @var \Blog\Service\PostServiceInterface
      */
     protected $postService;

     public function __construct(PostServiceInterface $postService)
     {
         $this->postService = $postService;
     }

     public function indexAction()
     {
         return new ViewModel(array(
             'posts' => $this->postService->findAllPosts()
         ));
     }
 }

請(qǐng)注意我們的控制器 import 了另外的類。我們需要 import Zend\View\Model\ViewModel,因?yàn)檫@基本是您的 Controller 會(huì)返回的數(shù)據(jù)類型。當(dāng)返回 ViewModel 的一個(gè)實(shí)例時(shí),你總能對(duì)所謂的“視圖變量”進(jìn)行賦值。在本示例中我們對(duì)一個(gè)叫做 $posts 的變量進(jìn)行了賦值,將其設(shè)為 PostService 中的 findAllPosts() 函數(shù)的返回值。在這個(gè)特例中返回值是一個(gè) Blog\Model\Post 類的數(shù)組。此時(shí)刷新瀏覽器會(huì)發(fā)現(xiàn)尚未有任何東西有不同,因?yàn)槲覀兒苊黠@需要先修改我們的視圖文件來顯示我們所需要的數(shù)據(jù)。

注意:事實(shí)上你并不一定需要返回 ViewModel 的實(shí)例。當(dāng)您返回一個(gè)普通的 php array,它也會(huì)隱式地被轉(zhuǎn)換成 ViewModel。所以簡(jiǎn)而言之: return new ViewModel(array('foo' => 'bar'));return array('foo' => 'bar'); 是完全等價(jià)的。

訪問視圖變量

若想將變量推送到視圖的時(shí)候,有兩種方法實(shí)現(xiàn)。要不就是直接像這個(gè)代碼 $this->posts,要不就是隱式地像 $posts。兩種方法都是一樣的,然而,隱式調(diào)用 $posts 時(shí)程序流會(huì)走多一步 __call() 函數(shù)。

我們來修改視圖文件,讓其顯示一個(gè)所有博客帖子(由 PostService 返回)的列表:

 <!-- 文件名: /module/Blog/view/blog/list/index.phtml -->
 <h1>Blog</h1>

 <?php foreach ($this->posts as $post): ?>
 <article>
     <h1 id="post<?= $post->getId() ?>"><?= $post->getTitle() ?></h1>
     <p>
         <?= $post->getText() ?>
     </p>
 </article>
 <?php endforeach ?>

此處我們簡(jiǎn)單地對(duì) $this->posts 使用一個(gè) foreach 循環(huán)。由于數(shù)組中每一個(gè)條目都是 Blog\Model\Post 類型的,所以可以使用其對(duì)應(yīng)的 getter 函數(shù)來獲得我們想要的內(nèi)容。

小結(jié)

在本章結(jié)束之時(shí),我們已經(jīng)掌握如何和 ServiceManager 進(jìn)行互動(dòng),同時(shí)也知道了依賴對(duì)象注入是個(gè)什么概念,也學(xué)會(huì)了將我們的 service 返回的變量通過 controller 傳給 view(視圖),然后在視圖腳本中遍歷整個(gè)數(shù)組。

在下一個(gè)章節(jié)中,我們會(huì)簡(jiǎn)單了解當(dāng)我們想從數(shù)據(jù)庫(kù)中獲得數(shù)據(jù)時(shí)所需要做的事情。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)