Yii - 快速指南



Yii - 概述

Yii[ji:] 框架是一個開源的 PHP 框架,用於快速開發現代 Web 應用程式。它構建在模型-檢視-控制器組合模式的基礎上。

Yii 提供安全且專業的特性,可以快速建立強大的專案。Yii 框架具有基於元件的架構和完整的快取支援。因此,它適用於構建各種 Web 應用程式:論壇、門戶、內容管理系統、RESTful 服務、電子商務網站等。它還有一個名為 Gii 的程式碼生成工具,其中包括完整的 CRUD(建立-讀取-更新-刪除)介面生成器。

核心特性

Yii 的核心特性如下:

  • Yii 實現了 MVC 架構模式。
  • 它提供了關係型資料庫和 NoSQL 資料庫的功能。
  • Yii 從不為了遵循某種設計模式而過度設計。
  • 它具有極強的擴充套件性。
  • Yii 提供多級快取支援。
  • Yii 提供 RESTful API 開發支援。
  • 它具有高效能。

總的來說,如果您只需要一個用於底層資料庫的簡潔介面,那麼 Yii 就是正確的選擇。目前,Yii 有兩個版本:1.1 和 2.0。

1.1 版現在處於維護模式,2.0 版採用了最新的技術,包括用於包分發的 Composer 工具、PSR 1、2 和 4 級別以及許多 PHP 5.4+ 功能。未來幾年,2.0 版將獲得主要的開發工作。

Yii 是一個純 OOP(面向物件程式設計)框架。因此,它需要具備 OOP 的基本知識。Yii 框架還使用了 PHP 的最新特性,如 trait 和名稱空間。如果您理解這些概念,那麼學習 Yii 2.0 會更容易。

環境

Yii2 的主要要求是 PHP 5.4+Web 伺服器。Yii 是一個強大的控制檯工具,它管理資料庫遷移、資源編譯和其他內容。建議您對開發應用程式的機器具有命令列訪問許可權。

出於開發目的,我們將使用:

  • Linux Mint 17.1
  • PHP 5.5.9
  • PHP 內建 Web 伺服器

預安裝檢查

要檢查您的本地機器是否可以使用最新的 Yii2 版本,請執行以下操作:

步驟 1 - 安裝最新版本的 php。

sudo apt-get install php5 

步驟 2 - 安裝最新版本的 mysql。

sudo apt-get install mysql-server

步驟 3 - 下載 Yii2 基本應用程式模板。

composer create-project --prefer-dist --stability=dev yiisoft/yii2-app-basic basic

步驟 4 - 要啟動 PHP 內建伺服器,在 basic 資料夾中執行。

php -S localhost:8080

有一個有用的指令碼,requirements.php。它檢查您的伺服器是否滿足執行應用程式的要求。您可以在應用程式的根資料夾中找到此指令碼。

Requirement PHP Script

如果您在 Web 瀏覽器的位址列中鍵入 https://:8080/requirements.php,則頁面將如下面的螢幕截圖所示:

Run Requirement PHP Script

Yii - 安裝

開始使用 Yii2 最簡單的方法是使用 Yii2 團隊提供的基本應用程式模板。此模板也可透過 Composer 工具獲得。

步驟 1 - 在您的硬碟驅動器中找到一個合適的目錄,並透過以下命令下載 Composer PHAR(PHP 存檔)。

curl -sS https://getcomposer.org/installer | php

步驟 2 - 然後將此存檔移動到 bin 目錄。

mv composer.phar /usr/local/bin/composer

步驟 3 - 安裝 Composer 後,您可以安裝 Yii2 基本應用程式模板。執行以下命令。

composer global require "fxp/composer-asset-plugin:~1.1.1" 
composer create-project --prefer-dist yiisoft/yii2-app-basic helloworld 

第一個命令安裝 composer asset 外掛,該外掛管理 npm 和 bower 依賴項。第二個命令在名為 helloworld 的目錄中安裝 Yii2 基本應用程式模板。

步驟 4 - 現在開啟 helloworld 目錄並啟動 PHP 中內建的 Web 伺服器。

php -S localhost:8080 -t web

步驟 5 - 然後在瀏覽器中開啟 https://:8080。您可以看到歡迎頁面。

Welcome Page

Yii - 建立頁面

現在我們將建立應用程式中的 “Hello world” 頁面。要建立頁面,我們必須建立一個操作和一個檢視。

操作在控制器中宣告。終端使用者將收到操作的執行結果。

步驟 1 - 在現有的 SiteController 中宣告 speak 操作,該操作在類檔案 controllers/SiteController.php 中定義。

<?php 
   namespace app\controllers; 
   use Yii; 
   use yii\filters\AccessControl; 
   use yii\web\Controller; 
   use yii\filters\VerbFilter; 
   use app\models\LoginForm; 
   use app\models\ContactForm; 
   class SiteController extends Controller { 
      /* other code */ 
      public function actionSpeak($message = "default message") { 
         return $this->render("speak",['message' => $message]); 
      } 
   } 
?>

我們將 speak 操作定義為名為 actionSpeak 的方法。在 Yii 中,所有操作方法都以單詞 action 為字首。這就是框架區分操作方法和非操作方法的方式。如果操作 ID 需要多個單詞,則它們將用連字元連線。因此,操作 ID add-post 對應於操作方法 actionAddPost

在上面給出的程式碼中,‘out’ 函式獲取一個 GET 引數 $message。我們還呼叫一個名為 ‘render’ 的方法來渲染名為 speak 的檢視檔案。我們將 message 引數傳遞給檢視。渲染結果是一個完整的 HTML 頁面。

檢視是一個生成響應內容的指令碼。對於 speak 操作,我們建立一個列印訊息的 speak 檢視。當呼叫 render 方法時,它會查詢一個名為 view/controllerID/vewName.php 的 PHP 檔案。

步驟 2 - 因此,在 views/site 資料夾內建立一個名為 speak.php 的檔案,其中包含以下程式碼。

<?php 
   use yii\helpers\Html; 
?> 
<?php echo Html::encode($message); ?> 

請注意,我們在列印 message 引數之前對其進行了 HTML 編碼,以避免 XSS 攻擊。

步驟 3 - 在您的 Web 瀏覽器中鍵入 https://:8080/index.php?r=site/speak&message=hello%20world

您將看到以下視窗:

Speak PHP File

URL 中的 ‘r’ 引數代表路由。路由的預設格式為 controllerID/actionID。在我們的例子中,路由 site/speak 將由 SiteController 類和 speak 操作解析。

Yii - 應用程式結構

在整個程式碼庫中,只有一個資料夾對 Web 伺服器公開可用。它是 web 目錄。web 根目錄之外的其他資料夾無法被 Web 伺服器訪問。

注意 - 所有專案依賴項都位於 composer.json 檔案中。Yii2 有幾個重要的包已由 Composer 包含在您的專案中。這些包如下:

  • Gii – 程式碼生成工具
  • 除錯控制檯
  • Codeception 測試框架
  • SwiftMailer 庫
  • Twitter Bootstrap UI 庫

前三個包僅在開發環境中才有用。

Yii2 的應用程式結構精確且清晰。它包含以下資料夾:

  • Assets - 此資料夾包含 Web 頁面中引用的所有 .js 和 .css 檔案。

  • Commands - 此資料夾包含可從終端使用的控制器。

  • Config - 此資料夾包含用於管理資料庫、應用程式和應用程式引數的 config 檔案。

  • Mail - 此資料夾包含郵件佈局。

  • Models - 此資料夾包含應用程式中使用的模型。

  • Runtime - 此資料夾用於儲存執行時資料。

  • Tests - 此資料夾包含所有測試(驗收、單元、功能)。

  • Vendor - 此資料夾包含由 Composer 管理的所有第三方包。

  • Views - 此資料夾用於由控制器顯示的檢視。layout 資料夾用於頁面模板。

  • Web - Web 的入口點。

應用程式結構

以下是應用程式結構的示意圖表示。

Application Structure

Yii2 – 物件

以下列表包含所有 Yii2 的物件:

模型、檢視和控制器

模型用於資料表示(通常來自資料庫)。檢視用於顯示資料。控制器用於處理請求並生成響應。

元件

要建立可重用的功能,使用者可以編寫自己的元件。元件只是包含邏輯的物件。例如,元件可以是重量轉換器。

應用程式元件

這些是在整個應用程式中僅例項化一次的物件。元件和應用程式元件之間的主要區別在於後者在整個應用程式中只能有一個例項。

小部件

小部件是可重用的物件,包含邏輯和渲染程式碼。例如,小部件可以是相簿滑塊。

過濾器

過濾器是在控制器操作執行之前或之後執行的物件。

模組

您可以將模組視為可重用的子應用程式,包含模型、檢視、控制器等。

擴充套件

擴充套件是可以由 Composer 管理的包。

Yii - 入口指令碼

入口指令碼負責啟動請求處理週期。它們只是使用者可以訪問的 PHP 指令碼。

下圖顯示了應用程式的結構:

Entry Scripts Structure

Web 應用程式(以及控制檯應用程式)具有單個入口指令碼。終端使用者向入口指令碼發出請求。然後,入口指令碼例項化應用程式例項並將請求轉發給它們。

控制檯應用程式的入口指令碼通常儲存在專案基本路徑中,並命名為 yii.php。Web 應用程式的入口指令碼必須儲存在 Web 可訪問的目錄下。它通常稱為 index.php

入口指令碼執行以下操作:

  • 定義常量。
  • 註冊 Composer 自動載入器。
  • 包含 Yii 檔案。
  • 載入配置。
  • 建立並配置應用程式例項。
  • 處理傳入的請求。

以下是 基本應用程式模板的入口指令碼:

<?php
   //defining global constants
   defined('YII_DEBUG') or define('YII_DEBUG', true);
   defined('YII_ENV') or define('YII_ENV', 'dev');
 
   //register composer autoloader
   require(__DIR__ . '/../vendor/autoload.php');
   //include yii files
   require(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php');
  
   //load application config
   $config = require(__DIR__ . '/../config/web.php');
  
   //create, config, and process reques
   (new yii\web\Application($config))->run();
?>

以下是 控制檯應用程式的入口指令碼:

#!/usr/bin/env php
<?php
   /** 
   * Yii console bootstrap file. 
   * @link http://www.yiiframework.com/ 
   * @copyright Copyright (c) 2008 Yii Software LLC 
   * @license http://www.yiiframework.com/license/ 
   */
   //defining global constants
   defined('YII_DEBUG') or define('YII_DEBUG', true);
  
   //register composer autoloader
   require(__DIR__ . '/vendor/autoload.php');
   require(__DIR__ . '/vendor/yiisoft/yii2/Yii.php');
  
   //load config
   $config = require(__DIR__ . '/config/console.php');
  
   //apply config the application instance 
   $application = new yii\console\Application($config);  

   //process request
   $exitCode = $application->run();
   exit($exitCode);
?>

定義全域性常量的最佳位置是入口指令碼。Yii 支援三個常量:

  • YII_DEBUG - 定義您是否處於除錯模式。如果設定為 true,我們將看到更多日誌資料和詳細的錯誤呼叫堆疊。

  • YII_ENV - 定義環境模式。預設值為 prod。可用值為 prod、dev 和 test。它們用於配置檔案中定義不同的資料庫連線(本地和遠端)或其他值。

  • YII_ENABLE_ERROR_HANDLER - 指定是否啟用預設的 Yii 錯誤處理程式。

要定義全域性常量,使用以下程式碼:

//defining global constants 
defined('YII_DEBUG') or define('YII_DEBUG', true); 
which is equivalent to: 
if(!defined('YII_DEBUG')) { 
   define('YII_DEBUG', true); 
} 

注意 − 全域性常量應定義在入口指令碼的開頭,以便在包含其他 PHP 檔案時生效。

Yii - 控制器

控制器負責處理請求並生成響應。在使用者請求後,控制器將分析請求資料,將其傳遞給模型,然後將模型結果插入檢視,並生成響應。

理解操作

控制器包含操作。它們是使用者可以請求執行的基本單元。一個控制器可以有一個或多個操作。

讓我們看一下基本應用程式模板的SiteController

<?php 
   namespace app\controllers; 
   use Yii; 
   use yii\filters\AccessControl; 
   use yii\web\Controller; 
   use yii\filters\VerbFilter; 
   use app\models\LoginForm; 
   use app\models\ContactForm; 
   class SiteController extends Controller { 
      public function behaviors() { 
         return [ 
            'access' => [ 
               'class' => AccessControl::className(), 
               'only' => ['logout'], 
               'rules' => [ 
                  [ 
                     'actions' => ['logout'], 
                     'allow' => true, 
                     'roles' => ['@'], 
                  ], 
               ], 
            ], 
            'verbs' => [
               'class' => VerbFilter::className(), 
               'actions' => [ 
                  'logout' => ['post'], 
               ], 
            ], 
         ]; 
      } 
      public function actions() { 
         return [ 
            'error' => [ 
               'class' => 'yii\web\ErrorAction', 
            ], 
            'captcha' => [ 
               'class' => 'yii\captcha\CaptchaAction', 
               'fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null, 
            ], 
         ]; 
      } 
      public function actionIndex() { 
         return $this->render('index'); 
      } 
      public function actionLogin() { 
         if (!\Yii::$app->user->isGuest) { 
            return $this->goHome(); 
         } 
         $model = new LoginForm(); 
         if ($model->load(Yii::$app->request->post()) && $model->login()) { 
            return $this->goBack(); 
         } 
         return $this->render('login', [ 
            'model' => $model, 
         ]); 
      }
      public function actionLogout() { 
         Yii::$app->user->logout();  
         return $this->goHome(); 
      } 
      public function actionContact() { 
         //load ContactForm model 
         $model = new ContactForm(); 
         //if there was a POST request, then try to load POST data into a model 
         if ($model->load(Yii::$app->request->post()) && $model>contact(Yii::$app->params
            ['adminEmail'])) { 
            Yii::$app->session->setFlash('contactFormSubmitted');  
            return $this->refresh(); 
         } 
         return $this->render('contact', [ 
            'model' => $model, 
         ]); 
      } 
      public function actionAbout() { 
         return $this->render('about'); 
      } 
      public function actionSpeak($message = "default message") { 
         return $this->render("speak",['message' => $message]); 
      } 
   } 
?>

使用 PHP 內建伺服器執行基本應用程式模板,並在 Web 瀏覽器中訪問https://:8080/index.php?r=site/contact。您將看到以下頁面 −

Run Basic Application

當您開啟此頁面時,SiteController 的 contact 操作將被執行。程式碼首先載入ContactForm 模型。然後它呈現 contact 檢視並將模型傳遞給它。

Contact Form Model

如果您填寫表單並單擊提交按鈕,您將看到以下內容 −

Submit Form

請注意,這次執行了以下程式碼 −

if ($model->load(Yii::$app->request->post()) && $model->contact(Yii::$app>params ['adminEmail'])) { 
   Yii::$app->session->setFlash('contactFormSubmitted'); 
   return $this->refresh(); 
} 

如果存在 POST 請求,我們將 POST 資料分配給模型並嘗試傳送電子郵件。如果成功,我們將設定一條帶有文字“感謝您的聯絡。我們會盡快回復您。”的快閃記憶體訊息並重新整理頁面。

理解路由

在上面的示例中,在 URL https://:8080/index.php?r=site/contact 中,路由是site/contactSiteController 中的 contact 操作(actionContact)將被執行。

路由由以下部分組成 −

  • moduleID − 如果控制器屬於某個模組,則路由的這部分存在。

  • controllerID(上例中的 site)− 一個唯一的字串,用於在同一模組或應用程式中的所有控制器中標識該控制器。

  • actionID(上例中的 contact)− 一個唯一的字串,用於在同一控制器中的所有操作中標識該操作。

路由的格式為controllerID/actionID。如果控制器屬於某個模組,則其格式如下:moduleID/controllerID/actionID

Yii - 使用控制器

Web 應用程式中的控制器應擴充套件自yii\web\Controller或其子類。在控制檯應用程式中,它們應擴充套件自yii\console\Controller或其子類。

讓我們在controllers資料夾中建立一個示例控制器。

步驟 1 − 在Controllers資料夾中,建立一個名為ExampleController.php的檔案,其中包含以下程式碼。

<?php 
   namespace app\controllers; 
   use yii\web\Controller; 
   class ExampleController extends Controller { 
      public function actionIndex() { 
         $message = "index action of the ExampleController"; 
         return $this->render("example",[ 
            'message' => $message 
         ]); 
      } 
   } 
?>

步驟 2 − 在views/example資料夾中建立一個示例檢視。在該資料夾中,建立一個名為example.php的檔案,其中包含以下程式碼。

<?php 
   echo $message; 
?>

每個應用程式都有一個預設控制器。對於 Web 應用程式,站點是控制器,而對於控制檯應用程式,幫助是控制器。因此,當開啟https://:8080/index.php URL 時,站點控制器將處理請求。您可以在應用程式配置中更改預設控制器。

考慮給定的程式碼 −

'defaultRoute' => 'main'

步驟 3 − 將上述程式碼新增到以下config/web.php中。

<?php 
   $params = require(__DIR__ . '/params.php'); 
   $config = [ 
      'id' => 'basic', 
      'basePath' => dirname(__DIR__), 
      'bootstrap' => ['log'], 
      'components' => [ 
         'request' => [ 
            // !!! insert a secret key in the following (if it is empty) - this is
               //required by cookie validation 
            'cookieValidationKey' => 'ymoaYrebZHa8gURuolioHGlK8fLXCKjO', 
         ], 
         'cache' => [ 
            'class' => 'yii\caching\FileCache', 
         ], 
         'user' => [ 
            'identityClass' => 'app\models\User', 
            'enableAutoLogin' => true, 
         ], 
         'errorHandler' => [ 
            'errorAction' => 'site/error', 
         ], 
         'mailer' => [ 
            'class' => 'yii\swiftmailer\Mailer', 
            // send all mails to a file by default. You have to set 
            // 'useFileTransport' to false and configure a transport 
            // for the mailer to send real emails. 
            'useFileTransport' => true, 
         ], 
         'log' => [ 
            'traceLevel' => YII_DEBUG ? 3 : 0, 
            'targets' => [ 
               [ 
                  'class' => 'yii\log\FileTarget',
                  'levels' => ['error', 'warning'], 
               ], 
            ], 
         ], 
         'db' => require(__DIR__ . '/db.php'), 
      ], 
      //changing the default controller 
      'defaultRoute' => 'example', 
      'params' => $params, 
   ]; 
   if (YII_ENV_DEV) { 
      // configuration adjustments for 'dev' environment 
      $config['bootstrap'][] = 'debug'; 
      $config['modules']['debug'] = [ 
         'class' => 'yii\debug\Module', 
      ]; 
      $config['bootstrap'][] = 'gii'; 
      $config['modules']['gii'] = [ 
         'class' => 'yii\gii\Module', 
      ]; 
   } 
   return $config; 
?> 						  

步驟 4 − 在 Web 瀏覽器的位址列中鍵入https://:8080/index.php,您將看到預設控制器是示例控制器。

Controller Example

注意 − 控制器 ID 應包含小寫英文字母、數字、正斜槓、連字元和下劃線。

要將控制器 ID 轉換為控制器類名,您應該執行以下操作 −

  • 從由連字元分隔的所有單詞中獲取第一個字母並將其轉換為大寫。
  • 刪除連字元。
  • 將正斜槓替換為反斜槓。
  • 新增 Controller 字尾。
  • 新增控制器名稱空間。

示例

  • page 變成app\controllers\PageController

  • post-article 變成app\controllers\PostArticleController

  • user/post-article 變成app\controllers\user\PostArticleController

  • userBlogs/post-article 變成app\controllers\userBlogs\PostArticleController

Yii - 使用操作

要在控制器類中建立操作,您應該定義一個以 action 開頭的公共方法。操作的返回值表示要傳送給終端使用者的響應。

步驟 1 − 讓我們在ExampleController中定義 hello-world 操作。

<?php 
   namespace app\controllers; 
   use yii\web\Controller; 
   class ExampleController extends Controller { 
      public function actionIndex() { 
         $message = "index action of the ExampleController"; 
         return $this->render("example",[ 
            'message' => $message 
         ]); 
      } 
      public function actionHelloWorld() { 
         return "Hello world!"; 
      } 
   } 
?>

步驟 2 − 在 Web 瀏覽器的位址列中鍵入https://:8080/index.php?r=example/hello-world。您將看到以下內容。

Hello World Action

操作 ID 通常是動詞,例如 create、update、delete 等。這是因為操作通常設計為對資源執行特定的更改。

操作 ID 只能包含以下字元 − 小寫英文字母、數字、連字元和下劃線。

操作有兩種型別:內聯和獨立。

內聯操作在控制器類中定義。操作的名稱以此方式從操作 ID 派生 −

  • 將操作 ID 中所有單詞的第一個字母轉換為大寫。
  • 刪除連字元。
  • 新增 action 字首。

示例

  • index 變成 actionIndex。
  • hello-world(如上例所示)變成 actionHelloWorld。

如果您計劃在不同的地方重用相同的操作,則應將其定義為獨立操作。

建立獨立操作類

要建立獨立操作類,您應該擴充套件yii\base\Action或子類,並實現run()方法。

步驟 1 − 在專案根目錄中建立一個 components 資料夾。在該資料夾中建立一個名為GreetingAction.php的檔案,其中包含以下程式碼。

<?php 
   namespace app\components;
   use yii\base\Action;
   class GreetingAction extends Action {
      public function run() {
         return "Greeting";
      }
   }
?>

我們剛剛建立了一個可重用的操作。要在ExampleController中使用它,我們應該透過重寫 actions() 方法在操作對映中宣告我們的操作。

步驟 2 − 以這種方式修改ExampleController.php檔案。

<?php
   namespace app\controllers;
   use yii\web\Controller;
   class ExampleController extends Controller {
      public function actions() {
         return [
            'greeting' => 'app\components\GreetingAction',
         ];
      }
      public function actionIndex() {
         $message = "index action of the ExampleController";
         
         return $this->render("example",[
            'message' => $message
         ]);
      }
      public function actionHelloWorld() {
         return "Hello world!";
      }
   }
?>

actions()方法返回一個數組,其值為類名,鍵為操作 ID。

步驟 3 − 訪問https://:8080/index.php?r=example/greeting。您將看到以下輸出。

Greeting Example

步驟 4 − 您還可以使用操作將使用者重定向到其他 URL。將以下操作新增到ExampleController.php

public function actionOpenGoogle() {
   // redirect the user browser to http://google.com
   return $this->redirect('http://google.com');
} 

現在,如果您開啟https://:8080/index.php?r=example/open-google,您將被重定向到http://google.com

操作方法可以接收引數,稱為操作引數。它們的值使用引數名稱作為鍵從$_GET中檢索。

步驟 5 − 將以下操作新增到我們的示例控制器。

public function actionTestParams($first, $second) {
   return "$first $second";
}

步驟 6 − 在 Web 瀏覽器的位址列中鍵入 URLhttps://:8080/index.php?r=example/testparams&first=hello&second=world,您將看到以下輸出。

Run Hello World Example

每個控制器都有一個預設操作。當路由僅包含控制器 ID 時,表示請求了預設操作。預設情況下,操作為index。您可以在控制器中輕鬆覆蓋此屬性。

步驟 7 − 以這種方式修改我們的ExampleController

<?php
   namespace app\controllers;
   use yii\web\Controller;
   class ExampleController extends Controller {
      public $defaultAction = "hello-world";
      /* other actions */
   }
?>

步驟 8 − 現在,如果您訪問https://:8080/index.php?r=example,您將看到以下內容。

Run Hello World Example1

為了滿足請求,控制器將經歷以下生命週期 −

  • 呼叫yii\base\Controller:init()方法。

  • 控制器根據操作 ID 建立一個操作。

  • 控制器依次呼叫 Web 應用程式、模組和控制器的beforeAction()方法。

  • 控制器執行操作。

  • 控制器依次呼叫 Web 應用程式、模組和控制器的afterAction()方法。

  • 應用程式將操作結果分配給響應。

重要事項

控制器應 −

  • 非常輕量級。每個操作都應只包含幾行程式碼。
  • 使用檢視進行響應。
  • 不嵌入 HTML。
  • 訪問請求資料。
  • 呼叫模型的方法。
  • 不處理請求資料。這些應在模型中處理。

Yii - 模型

模型是表示業務邏輯和規則的物件。要建立模型,您應該擴充套件yii\base\Model類或其子類。

屬性

屬性表示業務資料。它們可以像陣列元素或物件屬性一樣訪問。每個屬性都是模型的一個公共可訪問屬性。要指定模型擁有哪些屬性,您應該重寫yii\base\Model::attributes()方法。

讓我們看一下基本應用程式模板的ContactForm模型。

<?php
   namespace app\models;
   use Yii;
   use yii\base\Model;
   /**
   * ContactForm is the model behind the contact form.
   */
   class ContactForm extends Model {
      public $name;
      public $email;
      public $subject;
      public $body;
      public $verifyCode;
      /**
      * @return array the validation rules.
      */
      public function rules() {
         return [
            // name, email, subject and body are required
            [['name', 'email', 'subject', 'body'], 'required'],
            // email has to be a valid email address
            ['email', 'email'],
            // verifyCode needs to be entered correctly
            ['verifyCode', 'captcha'],
         ];
      }
      /**
      * @return array customized attribute labels
      */
      public function attributeLabels() {
         return [
            'verifyCode' => 'Verification Code',
         ];
      }
      /**
      * Sends an email to the specified email address using the information 
         collected by this model.
      * @param  string  $email the target email address
      * @return boolean whether the model passes validation
      */
      public function contact($email) {
         if ($this->validate()) {
            Yii::$app->mailer->compose()
               ->setTo($email)
               ->setFrom([$this->email => $this->name])
               ->setSubject($this->subject)
               ->setTextBody($this->body)
               ->send();
            return true;
         }
         return false;
      }
   }
?>

步驟 1 − 在SiteController中建立一個名為actionShowContactModel的函式,其中包含以下程式碼。

public function actionShowContactModel() { 
   $mContactForm = new \app\models\ContactForm(); 
   $mContactForm->name = "contactForm"; 
   $mContactForm->email = "user@gmail.com"; 
   $mContactForm->subject = "subject"; 
   $mContactForm->body = "body"; 
   var_dump($mContactForm); 
}

在上面的程式碼中,我們定義了ContactForm模型,設定了屬性,並在螢幕上顯示了模型。

步驟 2 − 現在,如果您在 Web 瀏覽器的位址列中鍵入https://:8080/index.php?r=site/show-contact-model,您將看到以下內容。

Show Contact View

如果您的模型擴充套件自yii\base\Model,則其所有成員變數(公共和非靜態)都是屬性。ContactForm模型中有五個屬性 − name、email、subject、body、verifyCode,您可以輕鬆新增新的屬性。

屬性標籤

您通常需要顯示與屬性關聯的標籤。預設情況下,屬性標籤由yii\base\Model::generateAttributeLabel()方法自動生成。要手動宣告屬性標籤,您可以重寫yii\base\Model::attributeLabels()方法。

步驟 1 − 如果您開啟https://:8080/index.php?r=site/contact,您將看到以下頁面。

Contact Form

請注意,屬性標籤與其名稱相同。

步驟 2 − 現在,以以下方式修改ContactForm模型中的attributeLabels函式。

public function attributeLabels() {
   return [
      'name' => 'name overridden',
      'email' => 'email overridden',
      'subject' => 'subject overridden',
      'body' => 'body overridden',
      'verifyCode' => 'verifyCode overridden',
   ];
}

步驟 3 − 如果您再次開啟https://:8080/index.php?r=site/contact,您會注意到標籤已更改,如下面的影像所示。

Contact Changed

場景

您可以在不同的場景中使用模型。例如,當訪客想要傳送聯絡表單時,我們需要所有模型屬性。當用戶想要執行相同操作時,他已登入,因此我們不需要他的姓名,因為我們可以輕鬆地從資料庫中獲取它。

要宣告場景,我們應該重寫scenarios()函式。它返回一個數組,其鍵為場景名稱,值為活動屬性。活動屬性是要驗證的屬性。它們也可以被批次賦值

步驟 1 − 以以下方式修改ContactForm模型。

<?php
   namespace app\models;
   use Yii;
   use yii\base\Model;
   /**
   * ContactForm is the model behind the contact form.
   */
   class ContactForm extends Model {
      public $name;
      public $email;
      public $subject;
      public $body;
      public $verifyCode;
      const SCENARIO_EMAIL_FROM_GUEST = 'EMAIL_FROM_GUEST';
      const SCENARIO_EMAIL_FROM_USER = 'EMAIL_FROM_USER';
      public function scenarios() {
         return [
            self::SCENARIO_EMAIL_FROM_GUEST => ['name', 'email', 'subject', 
               'body', 'verifyCode'],
            self::SCENARIO_EMAIL_FROM_USER => ['email' ,'subject', 'body', 
               'verifyCode'],
         ];
      }
      /**
      * @return array the validation rules.
      */
      public function rules() {
         return [
            // name, email, subject and body are required
            [['name', 'email', 'subject', 'body'], 'required'],
            // email has to be a valid email address
            ['email', 'email'],
            // verifyCode needs to be entered correctly
            ['verifyCode', 'captcha'],
         ];
      }
      /**
      * @return array customized attribute labels
      */
      public function attributeLabels() {
         return [
            'name' => 'name overridden',
            'email' => 'email overridden',
            'subject' => 'subject overridden',
            'body' => 'body overridden',
            'verifyCode' => 'verifyCode overridden',
         ];
      }
      /**
      * Sends an email to the specified email address using the information 
         collected by this model.
      * @param  string  $email the target email address
      * @return boolean whether the model passes validation
      */
      public function contact($email) {
         if ($this -> validate()) {
            Yii::$app->mailer->compose()
               ->setTo($email)
               ->setFrom([$this->email => $this->name]) 
               ->setSubject($this->subject) 
               ->setTextBody($this->body)
               ->send();
            return true;
         }
         return false;
      }
   }
?>

我們添加了兩個場景。一個用於訪客,另一個用於已認證的使用者。當用戶已認證時,我們不需要他的姓名。

步驟 2 − 現在,修改SiteControlleractionContact函式。

public function actionContact() {
   $model = new ContactForm();
   $model->scenario = ContactForm::SCENARIO_EMAIL_FROM_GUEST;
   if ($model->load(Yii::$app->request->post()) && $model->
      contact(Yii::$app->params ['adminEmail'])) {
         Yii::$app->session->setFlash('contactFormSubmitted');  
         return $this->refresh();
   }
   return $this->render('contact', [
      'model' => $model,
   ]);
}

步驟 3 − 在 Web 瀏覽器中鍵入https://:8080/index.php?r=site/contact。您會注意到當前所有模型屬性都是必需的。

Required Model Attributes

步驟 4 − 如果您在actionContact中更改模型的場景,如以下程式碼所示,您會發現 name 屬性不再是必需的。

$model->scenario = ContactForm::SCENARIO_EMAIL_FROM_USER;

Change Scenario

批次賦值

批次賦值是一種透過一行程式碼從多個輸入屬性建立模型的便捷方法。

程式碼行如下 −

$mContactForm = new \app\models\ContactForm; 
$mContactForm->attributes = \Yii::$app->request->post('ContactForm');

上面給出的程式碼行等效於 −

$mContactForm = new \app\models\ContactForm; 
$postData = \Yii::$app->request->post('ContactForm', []); 
$mContactForm->name = isset($postData['name']) ? $postData['name'] : null; 
$mContactForm->email = isset($postData['email']) ? $postData['email'] : null; 
$mContactForm->subject = isset($postData['subject']) ? $postData['subject'] : null; 
$mContactForm->body = isset($postData['body']) ? $postData['body'] : null;

前者更簡潔。請注意,批次賦值僅適用於安全屬性。它們只是scenario()函式中列出的當前場景屬性。

資料匯出

模型通常需要以不同的格式匯出。要將模型轉換為陣列,請修改SiteControlleractionShowContactModel函式 −

public function actionShowContactModel() {
   $mContactForm = new \app\models\ContactForm();
   $mContactForm->name = "contactForm";
   $mContactForm->email = "user@gmail.com";
   $mContactForm->subject = "subject";
   $mContactForm->body = "body";
   var_dump($mContactForm->attributes);
} 

在位址列中鍵入https://:8080/index.php?r=site/show-contact-model,您將看到以下內容 −

Data Export

要將模型轉換為JSON格式,請以以下方式修改actionShowContactModel函式 −

public function actionShowContactModel() {
   $mContactForm = new \app\models\ContactForm();
   $mContactForm->name = "contactForm";
   $mContactForm->email = "user@gmail.com";
   $mContactForm->subject = "subject";
   $mContactForm->body = "body";
   return \yii\helpers\Json::encode($mContactForm);
}

瀏覽器輸出

{
   "name":"contactForm",
   "email":"user@gmail.com",
   "subject":"subject",
   "body":"body ",
   "verifyCode":null
}

重要事項

在設計良好的應用程式中,模型通常比控制器快得多。模型應 −

  • 包含業務邏輯。
  • 包含驗證規則。
  • 包含屬性。
  • 不嵌入 HTML。
  • 不直接訪問請求。
  • 不要有太多場景。

Yii - 小部件

小部件是一個可重用的客戶端程式碼,包含 HTML、CSS 和 JS。此程式碼包含最少的邏輯,幷包裝在yii\base\Widget物件中。我們可以輕鬆地將此物件插入並應用到任何檢視中。

步驟 1 - 要檢視小部件的實際效果,請在SiteController中建立一個actionTestWidget函式,並使用以下程式碼。

public function actionTestWidget() { 
   return $this->render('testwidget'); 
}

在上面的示例中,我們只返回了一個名為“testwidget”View

步驟 2 - 現在,在views/site資料夾內,建立一個名為testwidget.php的View檔案。

<?php 
   use yii\bootstrap\Progress; 
?> 
<?= Progress::widget(['percent' => 60, 'label' => 'Progress 60%']) ?>

步驟 3 - 如果您訪問https://:8080/index.php?r=site/test-widget,您將看到進度條小部件。

Progress Bar

使用小部件

要在View中使用小部件,您應該呼叫yii\base\Widget::widget()函式。此函式接受一個配置陣列來初始化小部件。在前面的示例中,我們插入了一個進度條,並使用了配置物件的percent和labelled引數。

一些小部件需要一段內容。它應該包含在yii\base\Widget::begin()yii\base\Widget::end()函式之間。例如,以下小部件顯示了一個聯絡表單 -

<?php $form = ActiveForm::begin(['id' => 'contact-form']); ?> 
   <?= $form->field($model, 'name') ?> 
   <?= $form->field($model, 'email') ?> 
   <?= $form->field($model, 'subject') ?> 
   <?= $form->field($model, 'body')->textArea(['rows' => 6]) ?> 
   <?= $form->field($model, 'verifyCode')->widget(Captcha::className(), [ 
      'template' =>
         '<div class="row">
            <div class = "col-lg-3">{image}</div>
            <div class = "col-lg-6">{input}</div>
         </div>', 
   ]) ?> 
   <div class = "form-group"> 
      <?= Html::submitButton('Submit', ['class' => 'btn btn-primary',
         'name' => 'contact-button']) ?> 
   </div> 
<?php ActiveForm::end(); ?> 

建立小部件

要建立小部件,您應該從yii\base\Widget繼承。然後,您應該覆蓋yii\base\Widget::init()yii\base\Widget::run()函式。run()函式應返回渲染結果。init()函式應規範化小部件屬性。

步驟 1 - 在專案根目錄中建立一個components資料夾。在該資料夾內,建立一個名為FirstWidget.php的檔案,並使用以下程式碼。

<?php 
   namespace app\components; 
   use yii\base\Widget; 
   class FirstWidget extends Widget { 
      public $mes; 
      public function init() { 
         parent::init(); 
         if ($this->mes === null) { 
            $this->mes = 'First Widget'; 
         } 
      }  
      public function run() { 
         return "<h1>$this->mes</h1>"; 
      } 
   } 
?>

步驟 2 - 以以下方式修改testwidget檢視。

<?php 
   use app\components\FirstWidget; 
?> 
<?= FirstWidget∷widget() ?>

步驟 3 - 訪問https://:8080/index.php?r=site/test-widget。您將看到以下內容。

First Widget

步驟 4 - 要將內容包含在begin()end()呼叫之間,您應該修改FirstWidget.php檔案。

<?php
   namespace app\components;
   use yii\base\Widget;
   class FirstWidget extends Widget {
      public function init() {
         parent::init();
         ob_start();
      }
      public function run() {
         $content = ob_get_clean();
         return "<h1>$content</h1>";
      }
   }
?> 

步驟 5 - 現在h1標籤將包圍所有內容。請注意,我們使用ob_start()函式來緩衝輸出。按以下程式碼修改testwidget檢視。

<?php
   use app\components\FirstWidget;
?>
<?php FirstWidget::begin(); ?>
   First Widget in H1
<?php FirstWidget::end(); ?>

您將看到以下輸出 -

First Widget in H1

重要事項

小部件應該 -

  • 按照MVC模式建立。您應該將表示層保留在檢視中,將邏輯保留在小部件類中。

  • 設計為自包含的。最終開發者應該能夠將其設計到檢視中。

Yii - 模組

模組是一個擁有自己的模型、檢視、控制器以及可能的其他模組的實體。它實際上是應用程式內的應用程式。

步驟 1 - 在您的專案根目錄中建立一個名為modules的資料夾。在modules資料夾內,建立一個名為hello的資料夾。這將是我們Hello模組的基本資料夾。

步驟 2 - 在hello資料夾內,建立一個名為Hello.php的檔案,並使用以下程式碼。

<?php
   namespace app\modules\hello;
   class Hello extends \yii\base\Module {
      public function init() {
         parent::init();
      }
   }
?>

我們剛剛建立了一個模組類。它應該位於模組的基礎路徑下。每次訪問模組時,都會建立一個對應模組類的例項。init()函式用於初始化模組的屬性。

步驟 3 - 現在,在hello資料夾內新增另外兩個目錄 - controllers和views。將CustomController.php檔案新增到controllers資料夾中。

<?php
   namespace app\modules\hello\controllers;
   use yii\web\Controller;
   class CustomController extends Controller {
      public function actionGreet() {
         return $this->render('greet');
      }
   }
?>

建立模組時,約定將控制器類放在模組基礎路徑的controllers目錄中。我們剛剛定義了actionGreet函式,它只返回一個greet檢視。

模組中的檢視應放在模組基礎路徑的views資料夾中。如果檢視由控制器渲染,則它們應該位於對應於controllerID的資料夾中。將custom資料夾新增到views資料夾中。

步驟 4 - 在custom目錄內,建立一個名為greet.php的檔案,並使用以下程式碼。

<h1>Hello world from custom module!</h1>

我們剛剛為actionGreet建立了一個View。要使用這個新建立的模組,我們應該配置應用程式。我們應該將我們的模組新增到應用程式的modules屬性中。

步驟 5 - 修改config/web.php檔案。

<?php
   $params = require(__DIR__ . '/params.php');
   $config = [
      'id' => 'basic',
      'basePath' => dirname(__DIR__),
      'bootstrap' => ['log'],
      'components' => [
         'request' => [
            // !!! insert a secret key in the following (if it is empty) - this is
               //required by cookie validation
            'cookieValidationKey' => 'ymoaYrebZHa8gURuolioHGlK8fLXCKjO',
         ],
         'cache' => [
            'class' => 'yii\caching\FileCache',
         ],
         'user' => [
            'identityClass' => 'app\models\User',
            'enableAutoLogin' => true,
         ],
         'errorHandler' => [
            'errorAction' => 'site/error',
         ],
         'mailer' => [
            'class' => 'yii\swiftmailer\Mailer',
            // send all mails to a file by default. You have to set
            // 'useFileTransport' to false and configure a transport
            // for the mailer to send real emails.
            'useFileTransport' => true,
         ],
         'log' => [
            'traceLevel' => YII_DEBUG ? 3 : 0,
            'targets' => [
               [
                  'class' => 'yii\log\FileTarget',
                  'levels' => ['error', 'warning'],
               ],
            ],
         ],
         'db' => require(__DIR__ . '/db.php'),
      ],
      'modules' => [
         'hello' => [
            'class' => 'app\modules\hello\Hello', 
         ],
      ],
      'params' => $params,
   ];
   if (YII_ENV_DEV) {
      // configuration adjustments for 'dev' environment
      $config['bootstrap'][] = 'debug';
      $config['modules']['debug'] = [
         'class' => 'yii\debug\Module',
      ];
      $config['bootstrap'][] = 'gii';
      $config['modules']['gii'] = [
         'class' => 'yii\gii\Module',
      ];
   }
   return $config;
?>

模組控制器的路由必須以模組ID開頭,後跟控制器ID和操作ID。

步驟 6 - 要在我們的應用程式中執行actionGreet,我們應該使用以下路由。

hello/custom/greet

其中hello是模組ID,custom是控制器ID,greet是操作ID

步驟 7 - 現在,輸入https://:8080/index.php?r=hello/custom/greet,您將看到以下輸出。

Custom Module

重要事項

模組應該 -

  • 用於大型應用程式。您應該將其功能劃分為幾個組。每個功能組都可以開發為一個模組。

  • 可重用。一些常用的功能,如SEO管理或部落格管理,可以開發成模組,以便您可以在將來的專案中輕鬆重用它們。

Yii - 檢視

檢視負責將資料呈現給終端使用者。在Web應用程式中,View只是包含HTML和PHP程式碼的PHP指令碼檔案。

建立檢視

步驟 1 - 讓我們看看基本應用程式模板的“About”檢視。

<?php
   /* @var $this yii\web\View */
   use yii\helpers\Html;
   $this->title = 'About';
   $this->params['breadcrumbs'][] = $this->title;
?>
<div class="site-about">
   <h1><?= Html::encode($this->title) ?></h1>
   <p>
      This is the About page. You may modify the following file to customize its content:
   </p>
   <code><?= __FILE__ ?></code>
</div>

$this變數指的是管理和渲染此檢視模板的檢視元件。

這就是“About”頁面顯示的樣子 -

About Page

為了避免XSS攻擊,對來自終端使用者的資料進行編碼和/或過濾非常重要。您應該始終透過呼叫yii\helpers\Html::encode()對純文字進行編碼,並透過呼叫yii\helpers\HtmlPurifier對HTML內容進行編碼。

步驟 2 - 以以下方式修改“About”檢視。

<?php
   /* @var $this yii\web\View */
   use yii\helpers\Html;
   use yii\helpers\HtmlPurifier;
   $this->title = 'About';
   $this->params['breadcrumbs'][] = $this->title;
?>
<div class="site-about">
   <h1><?= Html::encode($this->title) ?></h1>
   <p>
      This is the About page. You may modify the following file to customize its content:
   </p>
   <p>
      <?= Html::encode("<script>alert('alert!');</script><h1>ENCODE EXAMPLE</h1>>") ?>
   </p>
   <p>
      <?= HtmlPurifier::process("<script>alert('alert!');</script><h1> HtmlPurifier EXAMPLE</h1>") ?>
   </p>
   <code><?= __FILE__ ?></code>
</div>

步驟 3 - 現在輸入https://:8080/index.php?r=site/about。您將看到以下螢幕。

About View

請注意,Html::encode()函式內的javascript程式碼顯示為純文字。HtmlPurifier::process()呼叫也是如此。只有h1標籤顯示。

檢視遵循以下約定 -

  • 由控制器渲染的檢視應放在@app/views/controllerID資料夾中。

  • 在小部件中渲染的檢視應放在widgetPath/views資料夾中。

要在控制器內渲染檢視,您可以使用以下方法 -

  • render() - 渲染檢視並應用佈局。

  • renderPartial() - 渲染檢視但不應用佈局。

  • renderAjax() - 渲染檢視但不應用佈局,但會注入所有已註冊的js和css檔案。

  • renderFile() - 在給定的檔案路徑或別名中渲染檢視。

  • renderContent() - 渲染靜態字串並應用佈局。

要在另一個檢視內渲染檢視,您可以使用以下方法 -

  • render() - 渲染檢視。

  • renderAjax() - 渲染檢視但不應用佈局,但會注入所有已註冊的js和css檔案。

  • renderFile() - 在給定的檔案路徑或別名中渲染檢視。

步驟 4 - 在views/site資料夾內,建立兩個檢視檔案:_part1.php和_part2.php

_part1.php -

<h1>PART 1</h1>

_part2.php -

<h1>PART 2</h1>

步驟 5 - 最後,在“About”檢視中渲染這兩個新建立的檢視。

<?php
   /* @var $this yii\web\View */
   use yii\helpers\Html;
   $this->title = 'About';
   $this->params['breadcrumbs'][] = $this->title;
?>
<div class="site-about">
   <h1><?= Html::encode($this->title) ?></h1>
   <p>
      This is the About page. You may modify the following file to customize its content:
   </p>
   <?= $this->render("_part1") ?>
   <?= $this->render("_part2") ?>
   <code><?= __FILE__ ?></code>
</div>

您將看到以下輸出 -

Create View Files

渲染檢視時,您可以使用檢視名稱或檢視檔案路徑/別名來定義檢視。檢視名稱按以下方式解析 -

  • 檢視名稱可以省略副檔名。例如,about檢視對應於about.php檔案。

  • 如果檢視名稱以“/”開頭,那麼如果當前活動模組是forum,並且檢視名稱是comment/post,則路徑將為@app/modules/forum/views/comment/post。如果沒有活動模組,則路徑將為@app/views/comment/post。

  • 如果檢視名稱以“//”開頭,則對應的路徑將為@app/views/ViewName。例如,//site/contact對應於@app/views/site/contact.php。

  • 如果檢視名稱是contact,並且上下文控制器是SiteController,則路徑將為@app/views/site/contact.php。

  • 如果price檢視在goods檢視中渲染,則如果它在@app/views/invoice/goods.php中渲染,則price將解析為@app/views/invoice/price.php。

在檢視中訪問資料

要在檢視中訪問資料,您應該將資料作為第二個引數傳遞給檢視渲染方法。

步驟 1 - 修改SiteControlleractionAbout

public function actionAbout() {
   $email = "admin@support.com";
   $phone = "+78007898100";
   return $this->render('about',[
      'email' => $email,
      'phone' => $phone
   ]);
}

在上面給出的程式碼中,我們將兩個變數$email$phone傳遞給About檢視進行渲染。

步驟 2 - 更改about檢視程式碼。

<?php
   /* @var $this yii\web\View */
   use yii\helpers\Html;
   $this->title = 'About';
   $this->params['breadcrumbs'][] = $this->title;
?>
<div class = "site-about">
   <h1><?= Html::encode($this->title) ?></h1>
   <p>
      This is the About page. You may modify the following file to customize its content:
   </p>
   <p>
      <b>email:</b> <?= $email ?>
   </p>
   <p>
      <b>phone:</b> <?= $phone ?>
   </p>
   <code><?= __FILE__ ?></code>
</div>

我們剛剛添加了兩個從SiteController接收到的變數。

步驟 3 - 在Web瀏覽器中輸入URLhttps://:8080/index.php?r=site/about,您將看到以下內容。

Change About View Code

Yii - 佈局

佈局表示多個檢視的公共部分,例如頁面標題和頁尾。預設情況下,佈局應儲存在views/layouts資料夾中。

讓我們看看基本應用程式模板的主佈局 -

<?php
   /* @var $this \yii\web\View */
   /* @var $content string */
   use yii\helpers\Html;
   use yii\bootstrap\Nav;
   use yii\bootstrap\NavBar;
   use yii\widgets\Breadcrumbs;
   use app\assets\AppAsset;
   AppAsset::register($this);
?>
<?php $this->beginPage() ?>
<!DOCTYPE html>
<html lang = "<?= Yii::$app->language ?>">
   <head>
      <meta charset = "<?= Yii::$app->charset ?>">
      <meta name = "viewport" content = "width = device-width, initial-scale = 1">
      <?= Html::csrfMetaTags() ?>
      <title><?= Html::encode($this->title) ?></title>
      <?php $this->head() ?>
   </head>
   <body>
      <?php $this->beginBody() ?>
         <div class = "wrap">
            <?php
               NavBar::begin([
                  'brandLabel' => 'My Company',
                  'brandUrl' => Yii::$app->homeUrl,
                  'options' => [
                     'class' => 'navbar-inverse navbar-fixed-top',
                  ],
               ]);
               echo Nav::widget([
                  'options' => ['class' => 'navbar-nav navbar-right'],
                  'items' => [
                     ['label' => 'Home', 'url' => ['/site/index']],
                     ['label' => 'About', 'url' => ['/site/about']],
                     ['label' => 'Contact', 'url' => ['/site/contact']],
                     Yii::$app->user->isGuest ?
                        ['label' => 'Login', 'url' => ['/site/login']] :
                        [
                           'label' => 'Logout (' . Yii::$app->user->identity->username.')',
                           'url' => ['/site/logout'],
                           'linkOptions' => ['data-method' => 'post']
                        ],
                  ],
               ]);
               NavBar::end();
            ?>
            <div class = "container">
               <?= Breadcrumbs::widget([
                  'links' => isset($this->params['breadcrumbs']) ? $this>params
                     ['breadcrumbs'] : [],
               ]) ?>
               <?= $content ?>
            </div>
         </div>
         <footer class = "footer">
            <div class = "container">
               <p class = "pull-left">© My Company <?= date('Y') ?></p>
               <p class = "pull-right"><?= Yii::powered() ?></p>
            </div>
         </footer>
      <?php $this->endBody() ?>
   </body>
</html>
<?php $this->endPage() ?>

此佈局生成所有頁面通用的HTML頁面。$content變數是內容檢視的渲染結果。以下方法觸發有關渲染過程的事件,以便在其他地方註冊的指令碼和標籤可以正確注入 -

  • head() - 應在head部分內呼叫。生成一個佔位符,它將被替換為針對head位置註冊的HTML。

  • beginBody() - 應在body部分開頭呼叫。觸發EVENT_BEGIN_BODY事件。生成一個佔位符,它將被替換為針對body開頭位置註冊的HTML。

  • endBody() - 應在body部分末尾呼叫。觸發EVENT_END_BODY事件。生成一個佔位符,它將被替換為針對body末尾位置註冊的HTML。

  • beginPage() - 應在佈局開頭呼叫。觸發EVENT_BEGIN_PAGE事件。

  • endPage() - 應在佈局末尾呼叫。觸發EVENT_END_PAGE事件。

建立佈局

步驟 1 - 在views/layouts目錄內,建立一個名為newlayout.php的檔案,並使用以下程式碼。

<?php
   /* @var $this \yii\web\View */
   /* @var $content string */
   use yii\helpers\Html;
   use yii\bootstrap\Nav;
   use yii\bootstrap\NavBar;
   use yii\widgets\Breadcrumbs;
   use app\assets\AppAsset;
   AppAsset::register($this);
?>
<?php $this->beginPage() ?>
<!DOCTYPE html>
<html lang = "<?= Yii::$app->language ?>">
   <head>
      <meta charset = "<?= Yii::$app->charset ?>">
      <meta name = "viewport" content = "width = device-width, initial-scale = 1">
      <? = Html::csrfMetaTags() ?>
      <title><? = Html::encode($this->title) ?></title>
      <?php $this->head() ?>
   </head>

   <body>
      <?php $this->beginBody() ?>
         <div class = "wrap"> 
            <div class = "container">
               <? = $content ?>
            </div>
         </div>
			
         <footer class = "footer">
            <div class = "container">
               <p class = "pull-left">© My Company <?= date('Y') ?></p>
               <p class = "pull-right"><? = Yii::powered() ?></p>
            </div>
         </footer>
      <?php $this->endBody() ?>
   </body>
	
</html>
<?php $this->endPage() ?>

我們去掉了頂部的選單欄。

步驟 2 - 要將此佈局應用於SiteController,請將$layout屬性新增到SiteController類中。

<?php
   namespace app\controllers;
   use Yii;
   use yii\filters\AccessControl;
   use yii\web\Controller;
   use yii\filters\VerbFilter;
   use app\models\LoginForm;
   use app\models\ContactForm;
   class SiteController extends Controller {
      public $layout = “newlayout”;
      /* other methods */
   }
?>

步驟 3 - 現在,如果您在Web瀏覽器中訪問SiteController的任何檢視,您將看到佈局已更改。

Change About Layout

步驟 4 - 要註冊各種元標籤,您可以在內容檢視中呼叫yii\web\View::registerMetaTag()

步驟 5 - 修改SiteController“About”檢視。

<?php
   /* @var $this yii\web\View */
   use yii\helpers\Html;
   $this->title = 'About';
   $this->params['breadcrumbs'][] = $this->title;
   $this->registerMetaTag(['name' => 'keywords', 'content' => 'yii, developing, views,
      meta, tags']);
   $this->registerMetaTag(['name' => 'description', 'content' => 'This is the description
      of this page!'], 'description');
?>
<div class="site-about">
   <h1><?= Html::encode($this->title) ?></h1>
   <p>
      This is the About page. You may modify the following file to customize its content:
   </p>
   <code><?= __FILE__ ?></code>
</div>

我們剛剛註冊了兩個元標籤 - keywords和description

步驟 6 − 現在訪問 https://:8080/index.php?r=site/about, 你會在頁面頭部區域找到元標籤,如下截圖所示。

Meta Tags

檢視觸發多個事件 −

  • EVENT_BEGIN_BODY − 在佈局中,由呼叫 yii\web\View::beginBody() 觸發。

  • EVENT_END_BODY − 在佈局中,由呼叫 yii\web\View::endBody() 觸發。

  • EVENT_BEGIN_PAGE − 在佈局中,由呼叫 yii\web\View::beginPage() 觸發。

  • EVENT_END_PAGE − 在佈局中,由呼叫 yii\web\View::endPage() 觸發。

  • EVENT_BEFORE_RENDER − 在控制器中,渲染檔案開始時觸發。

  • EVENT_AFTER_RENDER − 渲染檔案後觸發。

你可以響應這些事件,將內容注入到檢視中。

步驟 7 − 為了在 SiteControlleractionAbout 中顯示當前日期和時間,請按如下方式修改它。

public function actionAbout() {
   \Yii::$app->view->on(View::EVENT_BEGIN_BODY, function () {
      echo date('m.d.Y H:i:s');
   });
   return $this->render('about');
}

步驟 8 − 在網頁瀏覽器的位址列中輸入 https://:8080/index.php?r=site/about,你將看到如下內容。

Trigger Event Example

重要事項

為了使檢視更易於管理,你應該 −

  • 將複雜的檢視拆分為多個較小的檢視。
  • 使用佈局來處理通用的 HTML 部分(頁首、頁尾、選單等)。
  • 使用小部件。

檢視應該 −

  • 包含 HTML 和簡單的 PHP 程式碼來格式化和渲染資料。
  • 不處理請求。
  • 不修改模型屬性。
  • 不執行資料庫查詢。

Yii - 資源

資原始檔是一個檔案(css、js、影片、音訊或影像等),可以在網頁中引用。Yii 在**資源包**中管理資原始檔。資源包的目的是將一組相關的 JSCSS 檔案放在程式碼庫中,並能夠透過單個 PHP 呼叫來註冊它們。資源包還可以依賴於其他資源包。

在 assets 資料夾中,你會找到基本應用程式模板的資源包 −

<?php
   namespace app\assets;
   use yii\web\AssetBundle;
   /**
   * @author Qiang Xue <qiang.xue@gmail.com>
   * @since 2.0
   */
   class AppAsset extends AssetBundle {
      public $basePath = '@webroot';
      public $baseUrl = '@web';
      public $css = [
         'css/site.css',
      ];
      public $js = [];
      public $depends = [
         'yii\web\YiiAsset',
         'yii\bootstrap\BootstrapAsset',
      ];
   }
?>

上面的類指定資原始檔位於 @webroot 資料夾內,對應於 URL @web。該包不包含任何 JS 檔案,只包含一個 CSS 檔案。該包依賴於其他包 −

yii\web\YiiAsset 和 yii\bootstrap\BootstrapAsset。

AssetBundle 的屬性

以下是 AssetBundle 的屬性。

  • basePath − 定義一個包含此包中資原始檔的、可透過 Web 訪問的目錄。

  • baseUrl − 指定與 basePath 屬性對應的 URL。

  • js − 定義一個包含在此包中的 JS 檔案陣列。

  • css − 定義一個包含在此包中的 CSS 檔案陣列。

  • depends − 定義一個此包所依賴的資源包陣列。這意味著當前資源包的 CSS 和 JS 檔案將在宣告的依賴包之後包含。

  • sourcePath − 定義包含資原始檔的根目錄。如果根目錄無法透過 Web 訪問,則應設定此屬性。否則,應設定 basePathbaseUrl 屬性。

  • cssOptions − 定義將傳遞給 yii\web\View∷registerCssFile 函式的選項。

  • jsOptions − 定義將傳遞給 yii\web\View::registerJsFile 函式的選項。

  • publishOptions: 指定將傳遞給 yii\web\AssetManager::publish 函式的選項。

資原始檔的分類

根據位置,資原始檔可以分為 −

  • 源資原始檔 − 資原始檔位於無法透過 Web 直接訪問的目錄中。為了在頁面中使用源資原始檔,需要將它們複製到 Web 目錄中。此過程稱為**資原始檔釋出**。

  • 已釋出的資原始檔 − 資原始檔位於可透過 Web 訪問的目錄中

  • 外部資原始檔 − 資原始檔位於另一臺 Web 伺服器上。

使用資源包

步驟 1 − 在 assets 資料夾中,建立一個名為 DemoAsset.php 的新檔案,內容如下。

<?php
   namespace app\assets;
   use yii\web\AssetBundle;
   class DemoAsset extends AssetBundle {
      public $basePath = ‘@webroot’;
      public $baseUrl = ‘@web’;
      public $js = [‘js/demo.js’];
   }
?>

步驟 2 − 我們剛剛聲明瞭一個新的資源包,其中包含一個 demo.js 檔案。現在,在 web/js 資料夾中,建立一個名為 demo.js 的檔案,內容如下。

console.log("hello from demo asset");

步驟 3 − 要註冊新建立的資源包,請轉到 views/layouts 目錄,並在 main.php 檔案頂部新增以下行。

\app\assets\DemoAsset::register($this);

步驟 4 − 如果將 Web 瀏覽器指向 https://:8080/index.php,你應該會看到以下 Chrome 控制檯輸出。

Using Asset Bundles

你還可以定義 jsOptionscssOptions 屬性來自定義 CSS 和 JS 檔案在頁面中的包含方式。預設情況下,JS 檔案在結束 body 標籤之前包含。

步驟 5 − 要在頭部區域包含 JS 檔案,請按如下方式修改 DemoAsset.php 檔案。

<?php
   namespace app\assets;
   use yii\web\AssetBundle;
   use yii\web\View;
   class DemoAsset extends AssetBundle {
      public $basePath = '@webroot';
      public $baseUrl = '@web';
      public $js = ['js/demo.js'];
      public  $jsOptions = ['position' => View::POS_HEAD];
   }
?>

步驟 6 − 現在訪問 https://:8080/index.php, 你應該會看到 demo.js 指令碼包含在頁面的頭部區域。

Demoset PHP File

對於在生產模式下執行的 Web 應用程式,啟用資原始檔的 HTTP 快取是一種常見的做法。這樣做,最後修改時間戳將附加到所有已釋出的資原始檔中。

步驟 7 − 轉到 config 資料夾並修改 web.php 檔案,如下面的程式碼所示。

<?php
   $params = require(__DIR__ . '/params.php');
   $config = [
      'id' => 'basic',
      'basePath' => dirname(__DIR__),
      'bootstrap' => ['log'],
      'components' => [
         'assetManager' => [
            'appendTimestamp' => true,
         ],
         'request' => [
            // !!! insert a secret key in the following (if it is empty) - this is
               //required by cookie validation
            'cookieValidationKey' => 'ymoaYrebZHa8gURuolioHGlK8fLXCKjO',
         ],
         'cache' => [
            'class' => 'yii\caching\FileCache',
         ],
         'user' => [
            'identityClass' => 'app\models\User',
            'enableAutoLogin' => true,
         ],
         'errorHandler' => [
            'errorAction' => 'site/error',
         ],
         'mailer' => [
            'class' => 'yii\swiftmailer\Mailer',
            // send all mails to a file by default. You have to set
            // 'useFileTransport' to false and configure a transport
            // for the mailer to send real emails.
            'useFileTransport' => true,
         ],
         'log' => [
            'traceLevel' => YII_DEBUG ? 3 : 0,
            'targets' => [
               [
                  'class' => 'yii\log\FileTarget',
                  'levels' => ['error', 'warning'],
               ],
            ],
         ],
         'db' => require(__DIR__ . '/db.php'),
      ],
      'modules' => [
         'hello' => [
            'class' => 'app\modules\hello\Hello',
         ],
      ],
      'params' => $params,
   ];
   if (YII_ENV_DEV) {
      // configuration adjustments for 'dev' environment
      $config['bootstrap'][] = 'debug';
      $config['modules']['debug'] = [
         'class' => 'yii\debug\Module',
      ];
      $config['bootstrap'][] = 'gii';
      $config['modules']['gii'] = [
         'class' => 'yii\gii\Module',
      ];
   }
   return $config;
?>

我們添加了 AssetManager 元件並設定了 appendTimestamp 屬性。

步驟 8 − 現在在 Web 瀏覽器的位址列中輸入 https://:8080/index.php。你會注意到所有資原始檔現在都有一個時間戳,如下面的圖片所示。

Web PHP File

核心 Yii 資源包

以下是核心 Yii 資源包。

  • yii\web\JqueryAsset − 包含 jquery.js 檔案。

  • yii\web\YiiAsset − 包含 yii.js 檔案,該檔案實現了在模組中組織 JS 程式碼的機制。

  • yii\bootstrap\BootstrapAsset − 包含來自 Twitter Bootstrap 框架的 CSS 檔案。

  • yii\bootstrap\BootstrapPluginAsset − 包含來自 Twitter Bootstrap 框架的 JS 檔案。

  • yii\jui\JuiAsset − 包含來自 jQuery UI 庫的 CSS 和 JS 檔案。

Yii - 資源轉換

開發人員通常不編寫 CSSJS 程式碼,而是使用擴充套件語法,如 LESS、SCSS、Stylus 用於 CSS,以及 TypeScript、CoffeeScript 用於 JS。然後,他們使用特殊工具將這些檔案轉換為真正的 CSS 和 JS。

Yii 中的資原始檔管理器會自動將擴充套件語法中的資原始檔轉換為 CSS 和 JS。渲染檢視時,它將在頁面中包含 CSS 和 JS 檔案,而不是原始的擴充套件語法資原始檔。

步驟 1 − 按如下方式修改 DemoAsset.php 檔案。

<?php
   namespace app\assets;
   use yii\web\AssetBundle;
   use yii\web\View;
   class DemoAsset extends AssetBundle {
      public $basePath = '@webroot';
      public $baseUrl = '@web';
      public $js = [
         'js/demo.js',
         'js/greeting.ts'
      ];
      public  $jsOptions = ['position' => View::POS_HEAD];
   }
?>

我們剛剛添加了一個 TypeScript 檔案。

步驟 2 − 在 web/js 目錄中,建立一個名為 greeting.ts 的檔案,內容如下。

class Greeter {
   constructor(public greeting: string) { }
   greet() {
      return this.greeting;
   }
};
var greeter = new Greeter("Hello from typescript!");
console.log(greeter.greet());

在上面的程式碼中,我們定義了一個 Greeter 類,其中包含一個 greet() 方法。我們將問候語寫入 Chrome 控制檯。

步驟 3 − 訪問 URL https://:8080/index.php。你會注意到 greeting.ts 檔案已轉換為 greeting.js 檔案,如下面的截圖所示。

Greeting Ts File

輸出如下。

Greeting Ts File Output

Yii - 擴充套件

擴充套件程式是專門為在 Yii 應用程式中使用而設計的程式包。你可以將自己的程式碼作為擴充套件程式共享,或者使用第三方擴充套件程式來為應用程式新增功能。

使用擴充套件程式

大多數擴充套件程式都作為 Composer 包分發。Composer 從 Packagist 安裝包 - Composer 包的儲存庫。

要安裝第三方擴充套件程式,你應該 −

  • 將擴充套件程式新增到 composer.json 檔案中。

  • 執行 composer install。

新增日期和時間小部件

讓我們向專案中新增一個整潔的 datetime 小部件。

步驟 1 − 按如下方式修改基本應用程式模板的 composer.json 檔案。

{
   "name": "yiisoft/yii2-app-basic",
   "description": "Yii 2 Basic Project Template",
   "keywords": ["yii2", "framework", "basic", "project template"],
   "homepage": "http://www.yiiframework.com/",
   "type": "project",
   "license": "BSD-3-Clause",
   "support": {
      "issues": "https://github.com/yiisoft/yii2/issues?state=open",
      "forum": "http://www.yiiframework.com/forum/",
      "wiki": "http://www.yiiframework.com/wiki/",
      "irc": "irc://irc.freenode.net/yii",
      "source": "https://github.com/yiisoft/yii2"
   },
   "minimum-stability": "stable",
   "require": {
      "php": ">=5.4.0",
      "yiisoft/yii2": ">=2.0.5",
      "yiisoft/yii2-bootstrap": "*",
      "yiisoft/yii2-swiftmailer": "*",
      "kartik-v/yii2-widget-datetimepicker": "*"
   },
   "require-dev": {
      "yiisoft/yii2-codeception": "*",
      "yiisoft/yii2-debug": "*",
      "yiisoft/yii2-gii": "*",
      "yiisoft/yii2-faker": "*"
   },
   "config": {
      "process-timeout": 1800
   },
   "scripts": {
      "post-create-project-cmd": [
         "yii\\composer\\Installer::postCreateProject"
      ]
   },
   "extra": {
      "yii\\composer\\Installer::postCreateProject": {
         "setPermission": [
            {
               "runtime": "0777",
               "web/assets": "0777",
               "yii": "0755"
            }
         ],
         "generateCookieValidationKey": [
            "config/web.php"
         ]
      },
      "asset-installer-paths": {
         "npm-asset-library": "vendor/npm",
         "bower-asset-library": "vendor/bower"
      }
   }
}

我們已將依賴項 "kartik-v/yii2-widget-datetimepicker": "*" 新增到 required 部分。

步驟 2 − 現在,在專案根目錄中,執行 composer update 以更新所有依賴項。

Add Dependencies

我們剛剛安裝了擴充套件程式。你可以在 vendor/kartik-v/yii2widget-datetimepicker 資料夾中找到它。

步驟 3 − 要在頁面中顯示新安裝的小部件,請修改 SiteControlleractionAbout 方法的 About 檢視。

<?php
   /* @var $this yii\web\View */
   use kartik\datetime\DateTimePicker;
   use yii\helpers\Html;
   $this->title = 'About';
   $this->params['breadcrumbs'][] = $this->title;
   $this->registerMetaTag(['name' => 'keywords', 'content' => 'yii, developing, views,
      meta, tags']);
   $this->registerMetaTag(['name' => 'description',
      'content' => 'This is the description of this page!'], 'description');
?>
<div class="site-about">
   <h1><?= Html::encode($this->title) ?></h1>
   <p>
      This is the About page. You may modify the following file to customize its content:
   </p>
   <?php
      echo DateTimePicker::widget([
         'name' => 'dp_1',
         'type' => DateTimePicker::TYPE_INPUT,
         'value' => '23-Feb-1982 10:10',
         'pluginOptions' => [
            'autoclose'=>true,
            'format' => 'dd-M-yyyy hh:ii'
         ]
      ]);
   ?>
</div>

步驟 4 − 現在,透過 php -S localhost:8080t web 命令從專案根目錄執行內建的 php 伺服器。

步驟 5 − 訪問 https://:8080/index.php?r=site/about. 你會看到一個整潔的 datetime 選擇器,如下面的截圖所示。

Date Time Picker

Yii - 建立擴充套件

讓我們建立一個簡單擴充套件程式,顯示標準的 “Hello world” 訊息。此擴充套件程式將透過 Packagist 儲存庫分發。

步驟 1 − 在你的硬碟驅動器上建立一個名為 hello-world 的資料夾(但不要放在 Yii 基本應用程式模板中)。在 hello-world 目錄中,建立一個名為 composer.json 的檔案,內容如下。

{
    "name": "tutorialspoint/hello-world",
    "authors": [
        {
            "name": "tutorialspoint"
        }
    ],
    "require": {},
    "autoload": {
        "psr-0": {
            "HelloWorld": "src/"
        }
    }
}

我們聲明瞭我們正在使用 PSR-0 標準,所有擴充套件檔案都在 src 資料夾下。

步驟 2 − 建立以下目錄路徑:hello-world/src/HelloWorld

步驟 3 − 在 HelloWorld 資料夾中,建立一個名為 SayHello.php 的檔案,內容如下。

<?php
   namespace HelloWorld;
   class SayHello {
      public static function world() {
         return 'Hello World, Composer!';
      }
   }
?>

我們定義了一個 SayHello 類,其中包含一個 world 靜態函式,該函式返回我們的 hello 訊息。

步驟 4 − 擴充套件程式已準備就緒。現在在你的 github 帳戶中建立一個空儲存庫,並將此擴充套件程式推送到那裡。

hello-world 資料夾中執行 −

  • git init
  • git add
  • git commit -m “initial commit”
  • git remote add origin <YOUR_NEWLY_CREATED_REPOSITORY>
  • git push -u origin master
Push Extensions

我們剛剛將擴充套件程式傳送到 github。現在,轉到 https://packagist.org, 登入並點選頂部選單中的 “提交”

你會看到一個頁面,你應該在其中輸入你的 github 儲存庫以釋出它。

Enter github Repository

步驟 5 − 點選 “檢查” 按鈕,你的擴充套件程式就會發布。

Extension Publish

步驟 6 − 返回基本應用程式模板。將擴充套件程式新增到 composer.json 中。

{
   "name": "yiisoft/yii2-app-basic",
   "description": "Yii 2 Basic Project Template",
   "keywords": ["yii2", "framework", "basic", "project template"],
   "homepage": "http://www.yiiframework.com/",
   "type": "project",
   "license": "BSD-3-Clause",
   "support": {
      "issues": "https://github.com/yiisoft/yii2/issues?state=open",
      "forum": "http://www.yiiframework.com/forum/",
      "wiki": "http://www.yiiframework.com/wiki/",
      "irc": "irc://irc.freenode.net/yii",
      "source": "https://github.com/yiisoft/yii2"
   },
   "minimum-stability": "dev",
   "prefer-stable" : true,
   "require": {
      "php": ">=5.4.0",
      "yiisoft/yii2": ">=2.0.5",
      "yiisoft/yii2-bootstrap": "*",
      "yiisoft/yii2-swiftmailer": "*",
      "kartik-v/yii2-widget-datetimepicker": "*",
      "tutorialspoint/hello-world": "*"
   },
   "require-dev": {
      "yiisoft/yii2-codeception": "*",
      "yiisoft/yii2-debug": "*",
      "yiisoft/yii2-gii": "*",
      "yiisoft/yii2-faker": "*"
   },
   "config": {
      "process-timeout": 1800
   },
   "scripts": {
      "post-create-project-cmd": [
         "yii\\composer\\Installer::postCreateProject"
      ]
   },
   "extra": {
      "yii\\composer\\Installer::postCreateProject": {
         "setPermission": [
            {
               "runtime": "0777",
               "web/assets": "0777",
               "yii": "0755"
            }
         ],
         "generateCookieValidationKey": [
            "config/web.php"
         ]
      },
      "asset-installer-paths": {
         "npm-asset-library": "vendor/npm",
         "bower-asset-library": "vendor/bower"
      }
   }
}

步驟 7 − 在專案根資料夾中,執行 composer update 以安裝/更新所有依賴項。

Run Composer Update

步驟 8 − 我們的擴充套件程式應該已安裝。要使用它,請修改 SiteControlleractionAbout 方法的 About 檢視。

<?php
   /* @var $this yii\web\View */
   use yii\helpers\Html;
   $this->title = 'About';
   $this->params['breadcrumbs'][] = $this->title;
   $this->registerMetaTag(['name' => 'keywords', 'content' => 'yii, developing, views,
      meta, tags']);
   $this->registerMetaTag(['name' => 'description', 'content' => 'This is the
      description of this page!'], 'description');
?>
<div class = "site-about">
   <h1><?= Html::encode($this->title) ?></h1>
   <p>
      This is the About page. You may modify the following file to customize its content:
   </p>
   <h1><?= HelloWorld\SayHello::world();  ?></h1>
</div>

步驟 9 − 在 Web 瀏覽器中輸入 https://:8080/index.php?r=site/about。你將看到來自我們擴充套件程式的 hello world 訊息。

Hello World Message

Yii - HTTP 請求

請求由 yii\web\Request 物件表示,該物件提供有關 HTTP 標頭、請求引數、cookie 等資訊。

get()post() 方法返回請求元件的請求引數。

示例

$req = Yii::$app->request;
   /*
   * $get = $_GET;
   */
   $get = $req->get();

   /*
   * if(isset($_GET['id'])) {
   *     $id = $_GET['id'];
   * } else {
   *     $id = null;
   * }
   */
   $id = $req->get('id');
	
   /*
   * if(isset($_GET['id'])) {
   *     $id = $_GET['id'];
   * } else {
   *     $id = 1;
   * }
   */
   $id = $req->get('id', 1);
	
   /*
   * $post = $_POST;
	*/
   $post = $req->post();

   /*
   * if(isset($_POST['name'])) {       
   *     $name = $_POST['name'];          
   * } else {
   *     $name = null;
   * }
   */
   $name = $req->post('name');
		  
   /*
   * if(isset($_POST['name'])) {
   *     $name = $_POST['name'];
   * } else {
   *     $name = '';
   * }
   */
   $name = $req->post('name', '');

步驟 1 − 將 actionTestGet 函式新增到基本應用程式模板的 SiteController 中。

public function actionTestGet() {
   var_dump(Yii::$app->request->get());
}

步驟 2 − 現在訪問 https://:8080/index.php?r=site/testget&id=1&name=tutorialspoint&message=welcome,你將看到以下內容。

actionTestGet Function Output

要檢索其他請求方法(PATCH、DELETE 等)的引數,請使用 yii\web\Request::getBodyParam() 方法。

要獲取當前請求的 HTTP 方法,請使用 Yii::$app→request→method 屬性。

步驟 3 − 按如下所示修改 actionTestGet 函式。

public function actionTestGet() {
   $req = Yii::$app->request;
   if ($req->isAjax) {
      echo "the request is AJAX";
   }
   if ($req->isGet) {
      echo "the request is GET";
   }
   if ($req->isPost) {
      echo "the request is POST";
   }
   if ($req->isPut) {
      echo "the request is PUT";
   }
}

步驟 4 − 訪問 https://:8080/index.php?r=site/test-get。你將看到以下內容。

Get Request

請求元件提供了許多屬性來檢查請求的 URL。

步驟 5 − 按如下所示修改 actionTestGet 函式。

public function actionTestGet() {
   //the URL without the host
   var_dump(Yii::$app->request->url);
   
   //the whole URL including the host path
   var_dump(Yii::$app->request->absoluteUrl);
   
   //the host of the URL
   var_dump(Yii::$app->request->hostInfo);
   
   //the part after the entry script and before the question mark
   var_dump(Yii::$app->request->pathInfo);
   
   //the part after the question mark
   var_dump(Yii::$app->request->queryString);
   
   //the part after the host and before the entry script
   var_dump(Yii::$app->request->baseUrl);
   
   //the URL without path info and query string
   var_dump(Yii::$app->request->scriptUrl);
   
   //the host name in the URL
   var_dump(Yii::$app->request->serverName);
   
   //the port used by the web server
   var_dump(Yii::$app->request->serverPort);
}

步驟 6 − 在 Web 瀏覽器的位址列中,輸入 https://:8080/index.php?r=site/testget&id=1&name=tutorialspoint&message=welcome,你將看到以下內容。

Modify Actiontestget Function Output

步驟 7 − 要獲取 HTTP 標頭資訊,可以使用 yii\web\Request::$headers 屬性。按如下方式修改 actionTestGet 函式。

public function actionTestGet() { 
   var_dump(Yii::$app->request->headers); 
}

步驟 8 − 如果訪問 URL https://:8080/index.php?r=site/testget&id=1&name=tutorialspoint&message=welcome,你將看到如下所示的輸出。

Modified Actiontestget Function Output

要獲取客戶端機器的主機名和 IP 地址,請使用 userHostuserIP 屬性。

步驟 9 − 以這種方式修改actionTestGet 函式。

public function actionTestGet() {
   var_dump(Yii::$app->request->userHost);
   var_dump(Yii::$app->request->userIP);
}

步驟 10 − 訪問地址https://:8080/index.php?r=site/test-get,您將看到以下螢幕。

actionTestGet Function Output Screen

Yii - 響應

當 Web 應用程式處理請求時,它會生成一個響應物件,該物件包含 HTTP 標頭、正文和 HTTP 狀態程式碼。在大多數情況下,您將使用響應應用程式元件。預設情況下,它是一個yii\web\Response的例項。

要管理響應 HTTP 狀態程式碼,請使用yii\web\Response::$statusCode屬性。yii\web\Response::$statusCode的預設值為 200。

步驟 1 − 在SiteController中新增一個名為actionTestResponse的函式。

public function actionTestResponse() {
   Yii::$app→response->statusCode = 201;
}

步驟 2 − 如果您將 Web 瀏覽器指向https://:8080/index.php?r=site/testresponse,您應該會注意到 201 Created 響應 HTTP 狀態。

Created response HTTP status

如果要指示請求不成功,可以丟擲以下預定義的 HTTP 異常之一:

  • yii\web\BadRequestHttpException − 狀態程式碼 400。

  • yii\web\UnauthorizedHttpException − 狀態程式碼 401。

  • yii\web\ForbiddenHttpException − 狀態程式碼 403。

  • yii\web\NotFoundHttpException − 狀態程式碼 404。

  • yii\web\MethodNotAllowedHttpException − 狀態程式碼 405。

  • yii\web\NotAcceptableHttpException − 狀態程式碼 406。

  • yii\web\ConflictHttpException − 狀態程式碼 409。

  • yii\web\GoneHttpException − 狀態程式碼 410。

  • yii\web\UnsupportedMediaTypeHttpException − 狀態程式碼 415。

  • yii\web\TooManyRequestsHttpException − 狀態程式碼 429。

  • yii\web\ServerErrorHttpException − 狀態程式碼 500。

步驟 3 − 按以下程式碼所示修改actionTestResponse函式。

public function actionTestResponse() {
   throw new \yii\web\GoneHttpException;
}

步驟 4 − 在 Web 瀏覽器的位址列中鍵入https://:8080/index.php?r=site/test-response,您可以在以下影像中看到410 Gone響應 HTTP 狀態。

Gone Response HTTP Status

步驟 5 − 您可以透過修改響應元件的headers屬性來發送 HTTP 標頭。要向響應新增新標頭,請按以下程式碼中給出的方式修改actionTestResponse函式。

public function actionTestResponse() {
   Yii::$app->response->headers->add('Pragma', 'no-cache');
}

步驟 6 − 轉到https://:8080/index.php?r=site/test-response,您將看到我們的 Pragma 標頭。

Pragma header

Yii 支援以下響應格式:

  • HTML − 由 yii\web\HtmlResponseFormatter 實現。

  • XML − 由 yii\web\XmlResponseFormatter 實現。

  • JSON − 由 yii\web\JsonResponseFormatter 實現。

  • JSONP − 由 yii\web\JsonResponseFormatter 實現。

  • RAW − 沒有任何格式化的響應。

步驟 7 − 要以JSON格式響應,請修改actionTestResponse函式。

public function actionTestResponse() {
   \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
   return [
      'id' => '1',
      'name' => 'Ivan',
      'age' => 24,
      'country' => 'Poland',
      'city' => 'Warsaw'
   ];
}

步驟 8 − 現在,在位址列中鍵入https://:8080/index.php?r=site/test-response,您將看到以下JSON響應。

JSON response

Yii 透過傳送 Location HTTP 標頭來實現瀏覽器重定向。您可以呼叫yii\web\Response::redirect()方法將使用者瀏覽器重定向到 URL。

步驟 9 − 以這種方式修改actionTestResponse函式。

public function actionTestResponse() {
   return $this->redirect('https://tutorialspoint.tw/');
}

現在,如果您訪問https://:8080/index.php?r=site/test-response,您的瀏覽器將重定向到TutorialsPoint網站。

傳送檔案

Yii 提供以下方法來支援檔案傳送:

  • yii\web\Response::sendFile() − 傳送現有檔案。

  • yii\web\Response::sendStreamAsFile() − 將現有檔案流作為檔案傳送。

  • yii\web\Response::sendContentAsFile() − 將文字字串作為檔案傳送。

以這種方式修改 actionTestResponse 函式:

public function actionTestResponse() {
   return \Yii::$app->response->sendFile('favicon.ico');
}

鍵入https://:8080/index.php?r=site/test-response,您將看到一個用於favicon.ico檔案的下載對話方塊視窗:

favicon.ico File

在呼叫yii\web\Response::send()函式之前,不會發送響應。預設情況下,此方法在yii\base\Application::run()方法結束時呼叫。要傳送響應,yii\web\Response::send()方法將執行以下步驟:

  • 觸發yii\web\Response::EVENT_BEFORE_SEND事件。
  • 呼叫yii\web\Response::prepare()方法。
  • 觸發yii\web\Response::EVENT_AFTER_PREPARE事件。
  • 呼叫yii\web\Response::sendHeaders()方法。
  • 呼叫yii\web\Response::sendContent()方法。
  • 觸發yii\web\Response::EVENT_AFTER_SEND事件。

Yii - URL 格式

當 Yii 應用程式處理請求的 URL 時,首先,它會將 URL 解析為路由。然後,為了處理請求,此路由用於例項化相應的控制器操作。此過程稱為路由。反向過程稱為 URL 建立。urlManager應用程式元件負責路由和 URL 建立。它提供了兩種方法:

  • parseRequest() − 將請求解析為路由。

  • createUrl() − 從給定路由建立 URL。

URL 格式

urlManager應用程式元件支援兩種 URL 格式:

  • 預設格式使用查詢引數r來表示路由。例如,URL/index.php?r=news/view&id=5表示路由news/viewid查詢引數 5。

  • 漂亮的 URL 格式使用入口指令碼名稱的額外路徑。例如,在上一個示例中,漂亮的格式將為/index.php/news/view/5。要使用此格式,您需要設定 URL 規則。

要啟用漂亮的 URL 格式並隱藏入口指令碼名稱,請執行以下步驟:

步驟 1 − 以以下方式修改config/web.php檔案。

<?php
   $params = require(__DIR__ . '/params.php');
   $config = [
      'id' => 'basic',
      'basePath' => dirname(__DIR__),
      'bootstrap' => ['log'],
      'components' => [
         'request' => [
            // !!! insert a secret key in the following (if it is empty) -
               //this is required by cookie validation
            'cookieValidationKey' => 'ymoaYrebZHa8gURuolioHGlK8fLXCKjO',
         ],
         'cache' => [
            'class' => 'yii\caching\FileCache',
         ],
         'user' => [
            'identityClass' => 'app\models\User',
            'enableAutoLogin' => true,
         ],
         'errorHandler' => [
            'errorAction' => 'site/error',
         ],
         'mailer' => [
            'class' => 'yii\swiftmailer\Mailer',
            // send all mails to a file by default. You have to set
            // 'useFileTransport' to false and configure a transport
            // for the mailer to send real emails.
            'useFileTransport' => true,
         ],
         'log' => [
            'traceLevel' => YII_DEBUG ? 3 : 0,
            'targets' => [
               [
                  'class' => 'yii\log\FileTarget',
                  'levels' => ['error', 'warning'],
               ],
            ],
         ],
         'urlManager' => [ 
            'showScriptName' => false, 
            'enablePrettyUrl' => true 
         ], 
         'db' => require(__DIR__ . '/db.php'), 
      ], 
      'modules' => [
         'hello' => [
            'class' => 'app\modules\hello\Hello',
         ],
      ],
      'params' => $params,
   ];
   if (YII_ENV_DEV) {
      // configuration adjustments for 'dev' environment
      $config['bootstrap'][] = 'debug';
      $config['modules']['debug'] = [
         'class' => 'yii\debug\Module',
      ];
      $config['bootstrap'][] = 'gii';
      $config['modules']['gii'] = [
         'class' => 'yii\gii\Module',
      ];
   }
   return $config;
?>

我們剛剛啟用了漂亮的 URL 格式並停用了入口指令碼名稱。

步驟 2 − 現在,如果您在 Web 瀏覽器的位址列中鍵入https://:8080/site/about,您將看到漂亮的 URL 正在起作用。

Pretty URL

請注意,URL 不再是https://:8080/index.php?r=site/about

Yii - URL 路由

要更改應用程式的預設路由,您應該配置defaultRoute屬性。

步驟 1 − 以以下方式修改config/web.php檔案。

<?php
   $params = require(__DIR__ . '/params.php');
   $config = [
      'id' => 'basic',
      'basePath' => dirname(__DIR__),
      'bootstrap' => ['log'],
      'defaultRoute' => 'site/contact',
      'components' => [
         //other code
?>

步驟 2 − 轉到https://:8080/index.php。您將看到預設的contact頁面。

Contact Page

要暫時將應用程式置於維護模式,您應該配置yii\web\Application::$catchAll屬性。

步驟 3 − 將以下函式新增到SiteController

public function actionMaintenance() {
   echo "<h1>Maintenance</h1>";
}

步驟 4 − 然後,以以下方式修改config/web.php檔案。

<?php
   $params = require(__DIR__ . '/params.php');
   $config = [
      'id' => 'basic',
      'basePath' => dirname(__DIR__),
      'bootstrap' => ['log'],
      'catchAll' => ['site/maintenance'],
      'components' => [
         //OTHER CODE

步驟 5 − 現在輸入應用程式的任何 URL,您將看到以下內容。

Maintenance

建立 URL

要建立各種型別的 URL,您可以使用yii\helpers\Url::to()輔助方法。以下示例假定正在使用預設 URL 格式。

步驟 1 − 向SiteController新增一個actionRoutes()方法。

public function actionRoutes() {
   return $this->render('routes');
}

此方法僅呈現routes檢視。

步驟 2 − 在 views/site 目錄中,建立一個名為routes.php的檔案,內容如下。

<?php
   use yii\helpers\Url;
?>

<h4>
   <b>Url::to(['post/index']):</b>
   <?php
      // creates a URL to a route: /index.php?r = post/index
      echo Url::to(['post/index']);
   ?>
</h4>

<h4>
   <b>Url::to(['post/view', 'id' => 100]):</b>
   <?php
      // creates a URL to a route with parameters: /index.php?r = post/view&id=100
      echo Url::to(['post/view', 'id' => 100]);
   ?>
</h4>

<h4>
   <b>Url::to(['post/view', 'id' => 100, '#' => 'content']):</b>
   <?php
      // creates an anchored URL: /index.php?r = post/view&id=100#content
      echo Url::to(['post/view', 'id' => 100, '#' => 'content']);
   ?>
</h4>

<h4>
   <b>Url::to(['post/index'], true):</b>
   <?php
      // creates an absolute URL: http://www.example.com/index.php?r=post/index
      echo Url::to(['post/index'], true);
   ?>
</h4>

<h4>
   <b>Url::to(['post/index'], 'https'):</b>
   <?php
      // creates an absolute URL using the https scheme: https://www.example.com/index.php?r=post/index
      echo Url::to(['post/index'], 'https');
   ?>
</h4>

步驟 3 − 鍵入https://:8080/index.php?r=site/routes,您將看到to()函式的一些用法。

to Function

傳遞給yii\helpers\Url::to()方法的路由可以根據以下規則是相對的或絕對的:

  • 如果路由為空,則將使用當前請求的路由。

  • 如果路由沒有前導斜槓,則認為它是相對於當前模組的路由。

  • 如果路由不包含斜槓,則認為它是當前控制器的操作 ID。

yii\helpers\Url輔助類還提供了一些有用的方法。

步驟 4 − 按以下程式碼中給出的方式修改routes檢視。

<?php
   use yii\helpers\Url;
?>

<h4>
   <b>Url::home():</b>
   <?php
      // home page URL: /index.php?r=site/index
      echo Url::home();
   ?>
</h4>
 
<h4>
   <b>Url::base():</b>
   <?php
      // the base URL, useful if the application is deployed in a sub-folder of the Web root
      echo Url::base();
   ?>
</h4>
 
<h4>
   <b>Url::canonical():</b>
   <?php
      // the canonical URL of the currently requested URL
      // see https://en.wikipedia.org/wiki/Canonical_link_element
      echo Url::canonical();
   ?>
</h4>
 
<h4>
   <b>Url::previous():</b>
   <?php
      // remember the currently requested URL and retrieve it back in later requests
      Url::remember();
      echo Url::previous();
   ?>
</h4>

步驟 5 − 如果您在 Web 瀏覽器中輸入地址https://:8080/index.php?r=site/routes,您將看到以下內容。

Modified Routes View Outputs

Yii - URL 規則

URL 規則是yii\web\UrlRule的一個例項。當啟用漂亮的 URL 格式時,urlManager元件使用在其rules屬性中宣告的 URL 規則。

要解析請求,URL 管理器會按照宣告的順序獲取規則並查詢第一個規則。

步驟 1 − 修改config/web.php檔案中的urlManager元件。

'urlManager' => [
   'showScriptName' => false,
   'enablePrettyUrl' => true,
   'rules' => [
      'about' => 'site/about',
   ]
],

步驟 2 − 在 Web 瀏覽器中轉到https://:8080/about,您將看到關於頁面。

Modified urlManager Component

URL 規則可以與此模式關聯的查詢引數關聯:

<ParamName:RegExp>,其中:

  • ParamName − 引數名稱

  • RegExp − 用於匹配引數值的可選正則表示式

假設我們已宣告以下 URL 規則:

[
   'articles/<year:\d{4}>/<category>' => 'article/index',
   'articles' => 'article/index',
   'article/<id:\d+>' => 'article/view',
]

當規則用於解析時:

  • /index.php/articles 解析為 article/index
  • /index.php/articles/2014/php 解析為 article/index
  • /index.php/article/100 解析為 article/view
  • /index.php/articles/php 解析為 articles/php

當規則用於建立 URL時:

  • Url::to(['article/index']) 建立 /index.php/articles

  • Url::to(['article/index', 'year' => 2014, 'category' => 'php']) 建立 /index.php/articles/2014/php

  • Url::to(['article/view', 'id' => 100]) 建立 /index.php/article/100

  • Url::to(['article/view', 'id' => 100, 'source' => 'ad']) 建立 /index.php/article/100?source=ad

  • Url::to(['article/index', 'category' => 'php']) 建立 /index.php/article/index?category=php

要向 URL 新增字尾,您應該配置yii\web\UrlManager::$suffix屬性。

步驟 3 − 修改config/web.php檔案中的urlComponent

'urlManager' => [
   'showScriptName' => false,
   'enablePrettyUrl' => true,
   'enableStrictParsing' => true,
   'suffix' => '.html'
],

步驟 4 − 在 Web 瀏覽器的位址列中鍵入地址https://:8080/site/contact.html,您將在螢幕上看到以下內容。請注意html字尾。

Notice HTML Suffix

Yii - HTML 表單

當表單基於模型時,在 Yii 中建立此表單的常用方法是透過yii\widgets\ActiveForm類。在大多數情況下,表單具有相應的模型,用於資料驗證。如果模型表示來自資料庫的資料,則模型應派生自ActiveRecord類。如果模型捕獲任意輸入,則它應派生自yii\base\Model類。

讓我們建立一個登錄檔單。

步驟 1 − 在models資料夾中,建立一個名為RegistrationForm.php的檔案,內容如下。

<?php
   namespace app\models;
   use Yii;
   use yii\base\Model;
   class RegistrationForm extends Model {
      public $username;
      public $password;
      public $email;
      public $subscriptions;
      public $photos;
      /**
      * @return array customized attribute labels
      */
      public function attributeLabels() {
         return [
            'username' => 'Username',
            'password' => 'Password',
            'email' => 'Email',
            'subscriptions' => 'Subscriptions',
            'photos' => 'Photos',
         ];
      }
   }
?>

我們已為登錄檔單聲明瞭一個模型,其中包含五個屬性:使用者名稱、密碼、電子郵件、訂閱和照片。

步驟 2 − 要顯示此表單,請向SiteController新增actionRegistration方法。

public function actionRegistration() {
   $mRegistration = new RegistrationForm();
   return $this->render('registration', ['model' => $mRegistration]);
}

我們建立了一個RegistrationForm的例項,並將其傳遞給註冊檢視。現在,是時候建立檢視了。

步驟 3 − 在 views/site 資料夾中,新增一個名為registration.php的檔案,內容如下。

<?php
   use yii\bootstrap\ActiveForm;
   use yii\bootstrap\Html;
?>
<div class = "row">
   <div class = "col-lg-5">
      <?php $form = ActiveForm::begin(['id' => 'registration-form']); ?>
      <?= $form->field($model, 'username') ?>
      <?= $form->field($model, 'password')->passwordInput() ?>
      <?= $form->field($model, 'email')->input('email') ?>
      <?= $form->field($model, 'photos[]')->fileInput(['multiple'=>'multiple']) ?>
      <?= $form->field($model, 'subscriptions[]')->checkboxList(['a' => 'Item A',
         'b' => 'Item B', 'c' => 'Item C']) ?>
      <div class = "form-group">
         <?= Html::submitButton('Submit', ['class' => 'btn btn-primary',
            'name' => 'registration-button']) ?>
      </div>
      <?php ActiveForm::end(); ?>
   </div>
</div>

我們觀察到以下內容:

  • ActiveForm::begin()函式標記表單的開始。ActiveForm::begin()ActiveForm::end()函式之間的所有程式碼都將包裝在form標籤內。

  • 要在表單中建立欄位,您應該呼叫ActiveForm::field()方法。它建立所有input 和 label標籤。輸入名稱會自動確定。

  • 例如,password屬性將為RegistrationForm[password]。如果希望屬性採用陣列,則應將[ ]附加到屬性名稱。

步驟 4 − 如果您轉到 Web 瀏覽器的位址列並鍵入https://:8080/index.php?r=site/registration,您將看到我們的表單。

Registration

Yii - 驗證

您永遠不應該信任從使用者那裡收到的資料。要使用使用者輸入驗證模型,您應該呼叫yii\base\Model::validate()方法。如果驗證成功,它將返回一個布林值。如果存在錯誤,您可以從yii\base\Model::$errors屬性中獲取它們。

使用規則

要使validate()函式起作用,您應該覆蓋yii\base\Model::rules()方法。

步驟 1rules()方法按以下格式返回一個數組。

[
   // required, specifies which attributes should be validated
   ['attr1', 'attr2', ...],
   // required, specifies the type a rule.
   'type_of_rule',
   // optional, defines in which scenario(s) this rule should be applied
   'on' => ['scenario1', 'scenario2', ...],
   // optional, defines additional configurations
   'property' => 'value', ...
]

對於每個規則,您至少應定義規則適用的屬性以及應用的規則型別。

核心驗證規則包括:boolean、captcha、compare、date、default、double、each、email、exist、file、filter、image、ip、in、integer、match、number、required、safe、string、trim、unique、url。

步驟 2 − 在models資料夾中建立一個新的模型。

<?php
   namespace app\models;
   use Yii;
   use yii\base\Model;
   class RegistrationForm extends Model {
      public $username;
      public $password;
      public $email;
      public $country;
      public $city;
      public $phone;
      public function rules() {
         return [
            // the username, password, email, country, city, and phone attributes are
            //required
            [['username' ,'password', 'email', 'country', 'city', 'phone'], 'required'],
            // the email attribute should be a valid email address
            ['email', 'email'],
         ];
      }
   }
?>

我們已經為登錄檔單聲明瞭模型。該模型有五個屬性:username、password、email、country、city和phone。它們都是必填項,並且email屬性必須是有效的電子郵件地址。

步驟 3 − 將actionRegistration方法新增到SiteController中,我們在其中建立一個新的RegistrationForm模型並將其傳遞給檢視。

public function actionRegistration() {
   $model = new RegistrationForm();
   return $this->render('registration', ['model' => $model]);
}

步驟 4 − 為我們的登錄檔單新增一個檢視。在views/site資料夾中,建立一個名為registration.php的檔案,內容如下。

<?php
   use yii\bootstrap\ActiveForm;
   use yii\bootstrap\Html;
?>

<div class = "row">
   <div class = "col-lg-5">
      <?php $form = ActiveForm::begin(['id' => 'registration-form']); ?>
         <?= $form->field($model, 'username') ?>
         <?= $form->field($model, 'password')->passwordInput() ?>
         <?= $form->field($model, 'email')->input('email') ?>
         <?= $form->field($model, 'country') ?>
         <?= $form->field($model, 'city') ?>
         <?= $form->field($model, 'phone') ?>
         <div class = "form-group">
            <?= Html::submitButton('Submit', ['class' => 'btn btn-primary',
               'name' => 'registration-button']) ?>
         </div>
      <?php ActiveForm::end(); ?>
   </div>
</div>

我們使用ActiveForm小部件來顯示我們的登錄檔單。

步驟 5 − 如果您訪問本地主機https://:8080/index.php?r=site/registration並點選提交按鈕,您將看到驗證規則生效。

Validation Rules

步驟 6 − 要自定義username屬性的錯誤訊息,請按如下方式修改RegistrationFormrules()方法。

public function rules() {
   return [
      // the username, password, email, country, city, and phone attributes are required
      [['password', 'email', 'country', 'city', 'phone'], 'required'],
      ['username', 'required', 'message' => 'Username is required'],
      // the email attribute should be a valid email address
      ['email', 'email'],
   ];
}

步驟 7 − 訪問本地主機https://:8080/index.php?r=site/registration並點選提交按鈕。您會注意到username屬性的錯誤訊息已更改。

Change Username Property

步驟 8 − 要自定義驗證過程,您可以覆蓋這些方法。

  • yii\base\Model::beforeValidate(): 觸發

    yii\base\Model::EVENT_BEFORE_VALIDATE事件。

  • yii\base\Model::afterValidate(): 觸發

    yii\base\Model::EVENT_AFTER_VALIDATE事件。

步驟 9 − 要修剪country屬性周圍的空格並將city屬性的空輸入轉換為null,您可以使用trimdefault驗證器。

public function rules() {
   return [
      // the username, password, email, country, city, and phone attributes are required
      [['password', 'email', 'country', 'city', 'phone'], 'required'],
      ['username', 'required', 'message' => 'Username is required'],
      ['country', 'trim'],
      ['city', 'default'],
      // the email attribute should be a valid email address
      ['email', 'email'],
   ];
}

步驟 10 − 如果輸入為空,您可以為其設定預設值。

public function rules() {
   return [
      ['city', 'default', 'value' => 'Paris'],
   ];
}

如果city屬性為空,則將使用預設值“Paris”。

Yii - 特設驗證

有時您需要驗證與任何模型都不繫結的值。您可以使用yii\base\DynamicModel類,它支援動態定義屬性和規則。

步驟 1 − 將actionAdHocValidation方法新增到SiteController中。

public function actionAdHocValidation() {
   $model = DynamicModel::validateData([
      'username' => 'John',
      'email' => 'john@gmail.com'
   ], [
      [['username', 'email'], 'string', 'max' => 12],
      ['email', 'email'],
   ]);
	
   if ($model->hasErrors()) {
      var_dump($model->errors);
   } else {
      echo "success";
   }
}

在上面的程式碼中,我們定義了一個具有username和email屬性的“動態”模型並對其進行驗證。

步驟 2 − 在網頁瀏覽器的位址列中輸入https://:8080/index.php?r=site/ad-hoc-validation,您將看到錯誤訊息,因為我們的電子郵件長度為14個字元。

Fourteen Character Long

自定義驗證器

自定義驗證器有兩種型別:

  • 內聯驗證器
  • 獨立驗證器

內聯驗證器由模型方法或匿名函式定義。如果屬性驗證失敗,您應該呼叫yii\base\Model::addError()方法來儲存錯誤訊息。

以下RegistrationForm的示例驗證city屬性,因此它只能接受兩個值:London和Paris。

<?php
   namespace app\models;
   use Yii;
   use yii\base\Model;
   class RegistrationForm extends Model {
      public $username;
      public $password;
      public $email;
      public $country;
      public $city;
      public $phone;
      public function rules() {
         return [
            ['city', 'validateCity']
         ];
      }
      public function validateCity($attribute, $params) {
         if (!in_array($this->$attribute, ['Paris', 'London'])) {
            $this->addError($attribute, 'The city must be either "London" or "Paris".');
         }
      }
   }
?>

獨立驗證器擴充套件了yii\validators\Validator類。要實現驗證邏輯,您應該覆蓋yii\validators\Validator::validateAttribute()方法。

步驟 1 − 要使用獨立驗證器實現前面的示例,請將CityValidator.php檔案新增到components資料夾中。

<?php
   namespace app\components;
   use yii\validators\Validator;
   class CityValidator extends Validator {
      public function validateAttribute($model, $attribute) {
         if (!in_array($model->$attribute, ['Paris', 'London'])) {
            $this->addError($model, $attribute, 'The city must be either "Paris"
               or "London".');
         }
      }
   }
?>

步驟 2 − 然後,按如下方式修改RegistrationForm模型。

<?php
   namespace app\models;
   use app\components\CityValidator;
   use Yii;
   use yii\base\Model;
   class RegistrationForm extends Model {
      public $username;
      public $password;
      public $email;
      public $country;
      public $city;
      public $phone;
      public function rules() {
         return [
            ['city', CityValidator::className()]
         ];
      }
   }
?>

Yii - AJAX 驗證

username驗證應該只在伺服器端進行,因為只有伺服器擁有所需的資訊。在這種情況下,您可以使用基於AJAX的驗證。

步驟 1 − 要啟用AJAX驗證,請按如下方式修改registration檢視。

<?php
   use yii\bootstrap\ActiveForm;
   use yii\bootstrap\Html;
?>
  
<div class = "row">
   <div class = "col-lg-5">  
   
      <?php $form = ActiveForm::begin(['id' => 'registration-form', 
         'enableAjaxValidation' => true]); ?>  
      <?= $form->field($model, 'username') ?>  
      <?= $form->field($model, 'password')->passwordInput() ?>  
      <?= $form->field($model, 'email')->input('email') ?>  
      <?= $form->field($model, 'country') ?>  
      <?= $form->field($model, 'city') ?>  
      <?= $form->field($model, 'phone') ?>  
      <div class = "form-group">             
         <?= Html::submitButton('Submit', ['class' => 'btn btn-primary', 
            'name' => 'registration-button']) ?>
      </div>
      
      <?php ActiveForm::end(); ?>  
   </div>
</div>

我們還應該準備伺服器,以便它可以處理AJAX請求。

步驟 2 − 按如下方式修改SiteControlleractionRegistration方法。

public function actionRegistration() { 
   $model = new RegistrationForm(); 
   if (Yii::$app->request->isAjax && $model->load(Yii::$app->request>post())) { 
      Yii::$app->response->format = Response::FORMAT_JSON; 
      return ActiveForm::validate($model); 
   } 
   return $this->render('registration', ['model' => $model]); 
}

步驟 3 − 現在,訪問https://:8080/index.php?r=site/registration,您會注意到表單驗證是透過AJAX請求完成的。

Ajax Requests

Yii - 會話

會話使資料在各個頁面之間可訪問。會話在伺服器上的臨時目錄中建立一個檔案,所有會話變數都儲存在其中。在特定使用者訪問網站期間,此資料可供網站的所有頁面使用。

會話開始時,會發生以下情況:

  • PHP為該特定會話建立一個唯一的ID。

  • 在客戶端(瀏覽器)傳送一個名為PHPSESSID的cookie。

  • 伺服器在臨時資料夾中建立一個檔案,所有會話變數都儲存在其中。

  • 當伺服器想要從會話變數中檢索值時,PHP會自動從PHPSESSID cookie中獲取唯一的會話ID。然後,它在臨時目錄中查詢所需的檔案。

要啟動會話,您應該呼叫session_start()函式。所有會話變數都儲存在$_SESSION全域性變數中。您還可以使用isset()函式檢查會話變數是否已設定:

<?php
   session_start();
   if( isset( $_SESSION['number'] ) ) {
      $_SESSION['number'] += 1;
   }else {
      $_SESSION['number'] = 1;
   }
   $msg = "This page was visited ".  $_SESSION['number'];
   $msg .= "in this session.";
   echo $msg;
?>

要銷燬會話,您應該呼叫session_destroy()函式。要銷燬單個會話變數,請呼叫unset()函式:

<?php
   unset($_SESSION['number']);
   session_destroy();
?>

在Yii中使用會話

會話允許資料在使用者請求之間持久化。在PHP中,您可以透過$_SESSION變數訪問它們。在Yii中,您可以透過session應用程式元件訪問會話。

步驟 1 − 將actionOpenAndCloseSession方法新增到SiteController中。

public function actionOpenAndCloseSession() {
   $session = Yii::$app->session;
   // open a session
   $session->open();
   // check if a session is already opened
   if ($session->isActive) echo "session is active";
   // close a session
   $session->close();
   // destroys all data registered to a session
   $session->destroy();
}

在上面的程式碼中,我們獲取session應用程式元件,開啟會話,檢查它是否處於活動狀態,關閉會話,最後銷燬它。

步驟 2 − 在網頁瀏覽器的位址列中輸入https://:8080/index.php?r=site/open-and-close-session,您將看到以下內容。

Session Active

要訪問會話變數,您可以使用set()get()方法。

步驟 3 − 將actionAccessSession方法新增到SiteController中。

public function actionAccessSession() {

   $session = Yii::$app->session;
	
   // set a session variable
   $session->set('language', 'ru-RU');
	
   // get a session variable
   $language = $session->get('language');
   var_dump($language);
		  
   // remove a session variable
   $session->remove('language');
		  
   // check if a session variable exists
   if (!$session->has('language')) echo "language is not set";
		  
   $session['captcha'] = [
      'value' => 'aSBS23',
      'lifetime' => 7200,
   ];
   var_dump($session['captcha']);
}

步驟 4 − 訪問https://:8080/index.php?r=site/access-session,您將看到以下內容。

Action Session

Yii - 使用快閃記憶體資料

Yii提供了快閃記憶體資料概念。快閃記憶體資料是會話資料,它:

  • 在一個請求中設定。
  • 僅在下一次請求中可用。
  • 之後將自動刪除。

步驟 1 − 將actionShowFlash方法新增到SiteController中。

public function actionShowFlash() {
   $session = Yii::$app->session;
   // set a flash message named as "greeting"
   $session->setFlash('greeting', 'Hello user!');
   return $this->render('showflash');
}

步驟 2 − 在views/site資料夾中,建立一個名為showflash.php的檢視檔案。

<?php
   use yii\bootstrap\Alert;
   echo Alert::widget([
      'options' => ['class' => 'alert-info'],
      'body' => Yii::$app->session->getFlash('greeting'),
   ]);
?>

步驟 3 − 當您在網頁瀏覽器的位址列中輸入https://:8080/index.php?r=site/show-flash時,您將看到以下內容。

showflash php file

Yii還提供以下會話類:

  • yii\web\CacheSession − 將會話資訊儲存在快取中。

  • yii\web\DbSession − 將會話資訊儲存在資料庫中。

  • yii\mongodb\Session − 將會話資訊儲存在MongoDB中。

  • yii\redis\Session − 使用redis資料庫儲存會話資訊。

Yii - Cookie

Cookie是儲存在客戶端的純文字檔案。您可以將其用於跟蹤目的。

識別回頭客有三個步驟:

  • 伺服器向客戶端(瀏覽器)傳送一組Cookie。例如,id或token。

  • 瀏覽器將其儲存。

  • 下次瀏覽器向Web伺服器傳送請求時,它還會發送這些Cookie,以便伺服器可以使用這些資訊來識別使用者。

Cookie通常在HTTP標頭中設定,如下面的程式碼所示。

HTTP/1.1 200 OK
Date: Fri, 05 Feb 2015 21:03:38 GMT
Server: Apache/1.3.9 (UNIX) PHP/4.0b3
Set-Cookie: name = myname; expires = Monday, 06-Feb-16 22:03:38 GMT;
   path = /; domain = tutorialspoint.com 
Connection: close
Content-Type: text/html

PHP提供setcookie()函式來設定Cookie:

setcookie(name, value, expire, path, domain, security);

其中:

  • name − 設定Cookie的名稱,並存儲在名為HTTP_COOKIE_VARS的環境變數中。

  • value − 設定命名變數的值。

  • expiry − 指定自1970年1月1日00:00:00 GMT以來的秒數的未來時間。在此時間之後,Cookie將變得不可訪問。

  • path − 指定Cookie有效的目錄。

  • domain − 這可用於在非常大的域中定義域名。所有Cookie僅對建立它們的宿主和域有效。

  • security − 如果設定為1,則表示Cookie應該只通過HTTPS傳送,否則,當設定為0時,Cookie可以透過常規HTTP傳送。

要訪問PHP中的Cookie,您可以使用$_COOKIE或$HTTP_COOKIE_VARS變數。

<?php 
   echo $_COOKIE["token"]. "<br />"; 
   /* is equivalent to */ 
   echo $HTTP_COOKIE_VARS["token"]. "<br />"; 
   echo $_COOKIE["id"] . "<br />"; 
   /* is equivalent to */ 
   echo $HTTP_COOKIE_VARS["id"] . "<br />"; 
?>

要刪除Cookie,您應該將Cookie設定為已過期的日期。

<?php 
   setcookie( "token", "", time()- 60, "/","", 0); 
   setcookie( "id", "", time()- 60, "/","", 0); 
?>

Yii - 使用 Cookie

Cookie允許資料在請求之間持久化。在PHP中,您可以透過$_COOKIE變數訪問它們。Yii將Cookie表示為yii\web\Cookie類的物件。在本章中,我們描述了幾種讀取Cookie的方法。

步驟 1 − 在SiteController中建立一個actionReadCookies方法。

public function actionReadCookies() { 
   // get cookies from the "request" component 
   $cookies = Yii::$app->request->cookies; 
   // get the "language" cookie value 
   // if the cookie does not exist, return "ru" as the default value 
   $language = $cookies->getValue('language', 'ru'); 
   // an alternative way of getting the "language" cookie value 
   if (($cookie = $cookies->get('language')) !== null) { 
      $language = $cookie->value; 
   } 
   // you may also use $cookies like an array 
   if (isset($cookies['language'])) { 
      $language = $cookies['language']->value; 
   } 
   // check if there is a "language" cookie 
   if ($cookies->has('language')) echo "Current language: $language"; 
}

步驟 2 − 要檢視Cookie的傳送情況,請在SiteController中建立一個名為actionSendCookies的方法。

public function actionSendCookies() { 
   // get cookies from the "response" component 
   $cookies = Yii::$app->response->cookies; 
   // add a new cookie to the response to be sent 
   $cookies->add(new \yii\web\Cookie([ 
      'name' => 'language', 
      'value' => 'ru-RU', 
   ])); 
   $cookies->add(new \yii\web\Cookie([
      'name' => 'username', 
      'value' => 'John', 
   ])); 
   $cookies->add(new \yii\web\Cookie([ 
      'name' => 'country', 
      'value' => 'USA', 
   ])); 
} 

步驟 3 − 現在,如果您訪問https://:8080/index.php?r=site/send-cookies,您會注意到Cookie已儲存在瀏覽器中。

Save Cookies

在Yii中,預設情況下,啟用Cookie驗證。它可以防止Cookie在客戶端被修改。來自config/web.php檔案的雜湊字串對每個Cookie進行簽名。

<?php 
   $params = require(__DIR__ . '/params.php'); 
   $config = [ 
      'id' => 'basic', 
      'basePath' => dirname(__DIR__), 
      'bootstrap' => ['log'], 
      'components' => [ 
         'request' => [ 
            // !!! insert a secret key in the following (if it is empty) - this is 
            //required by cookie validation 
            'cookieValidationKey' => 'ymoaYrebZHa8gURuolioHGlK8fLXCKjO', 
         ], 
         'cache' => [ 
            'class' => 'yii\caching\FileCache', 
         ], 
         'user' => [ 
            'identityClass' => 'app\models\User', 
            'enableAutoLogin' => true, 
         ], 
         'errorHandler' => [ 
            'errorAction' => 'site/error', 
         ], 
         'mailer' => [ 
            'class' => 'yii\swiftmailer\Mailer', 
            // send all mails to a file by default. You have to set 
            // 'useFileTransport' to false and configure a transport 
            // for the mailer to send real emails. 
            'useFileTransport' => true, 
         ], 
         'log' => [ 
            'traceLevel' => YII_DEBUG ? 3 : 0, 
            'targets' => [ 
               [ 
                  'class' => 'yii\log\FileTarget', 
                     'levels' => ['error', 'warning'], 
                ], 
            ], 
         ], 
         'urlManager' => [ 
            //'showScriptName' => false, 
            //'enablePrettyUrl' => true, 
            //'enableStrictParsing' => true, 
            //'suffix' => '/' 
         ], 
         'db' => require(__DIR__ . '/db.php'), 
      ], 
      'modules' => [ 
         'hello' => [ 
            'class' => 'app\modules\hello\Hello', 
         ], 
      ], 
      'params' => $params,
   ]; 
   if (YII_ENV_DEV) { 
      // configuration adjustments for 'dev' environment 
      $config['bootstrap'][] = 'debug'; 
      $config['modules']['debug'] = [ 
         'class' => 'yii\debug\Module', 
      ]; 
      $config['bootstrap'][] = 'gii'; 
      $config['modules']['gii'] = [ 
         'class' => 'yii\gii\Module', 
      ]; 
   } 
   return $config; 
?>

您可以透過將yii\web\Request::$enableCookieValidation屬性設定為false來停用Cookie驗證。

Yii - 檔案上傳

您可以藉助yii\web\UploadedFile、modelsyii\widgets\ActiveForm輕鬆實現檔案上傳功能。

在根資料夾中建立一個名為“uploads”的目錄。此目錄將儲存所有上傳的影像。要上傳單個檔案,您需要建立一個模型以及用於上傳檔案例項的模型屬性。您還應該驗證檔案上傳。

步驟 1 − 在models資料夾中,建立一個名為UploadImageForm.php的檔案,內容如下。

<?php
   namespace app\models;
   use yii\base\Model;
   class UploadImageForm extends Model {
      public $image;
      public function rules() {
         return [
            [['image'], 'file', 'skipOnEmpty' => false, 'extensions' => 'jpg, png'],
         ];
      }
      public function upload() {
         if ($this->validate()) {
            $this->image->saveAs('../uploads/' . $this->image->baseName . '.' .
               $this->image->extension);
            return true;
         } else {
            return false;
         }
      }
   }
?>

image屬性用於儲存檔案例項。file驗證規則確保檔案具有pngjpg副檔名。upload函式驗證檔案並將其儲存到伺服器上。

步驟 2 − 現在,將actionUploadImage函式新增到SiteController中。

public function actionUploadImage() {
   $model = new UploadImageForm();
   if (Yii::$app->request->isPost) {
      $model->image = UploadedFile::getInstance($model, 'image');
      if ($model->upload()) {
         // file is uploaded successfully
         echo "File successfully uploaded";
         return;
     }
   }
   return $this->render('upload', ['model' => $model]);
}

步驟 3 − 當表單提交時,我們呼叫yii\web\UploadedFile::getInstance()函式將上傳的檔案表示為UploadedFile例項。然後,我們驗證檔案並將其儲存到伺服器上。

步驟 4 − 接下來,在views/site目錄中建立一個upload.php檢視檔案。

<?php
   use yii\widgets\ActiveForm;
?>
<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']])?>
<?= $form->field($model, 'image')->fileInput() ?>
   <button>Submit</button>
<?php ActiveForm::end() ?>

請記住,在上傳檔案時新增enctype選項。fileInput()方法呈現以下html程式碼:

<input type = "file">

以上html程式碼允許使用者選擇和上傳檔案。

步驟 5 − 現在,如果您訪問https://:8080/index.php?r=site/upload-image,您將看到以下內容。

Select Upload Files

步驟 6 − 選擇要上傳的影像並單擊“提交”按鈕。該檔案將儲存在伺服器上的'uploads'資料夾中。

Uploads

Yii - 格式化

要以可讀格式顯示資料,您可以使用formatter應用程式元件。

步驟 1 − 將actionFormatter方法新增到SiteController中。

public function actionFormatter(){
   return $this->render('formatter');
}

在上面的程式碼中,我們只是渲染了formatter檢視。

步驟 2 − 現在,在views/site資料夾中建立一個formatter.php檢視檔案。

<?php
   $formatter = \Yii::$app->formatter;
   // output: January 1, 2016
   echo $formatter->asDate('2016-01-01', 'long'),"<br>";
   // output: 51.50%
   echo $formatter->asPercent(0.515, 2),"<br>";
   // output: <a href = "mailto:test@test.com">test@test.com</a>
   echo $formatter->asEmail('test@test.com'),"<br>";
   // output: Yes
   echo $formatter->asBoolean(true),"<br>";
   // output: (Not set)
   echo $formatter->asDate(null),"<br>";
?>

步驟 3 − 訪問https://:8080/index.php?r=site/formatter,您將看到以下輸出。

View File

formatter元件支援以下與日期和時間相關的格式:

輸出格式 示例
date 2016年1月1日
time 16:06
datetime 2016年1月1日 16:06
timestamp 1512609983
relativeTime 1小時前
duration 5分鐘

步驟 4 − 以這種方式修改formatter檢視。

<?php
   $formatter = \Yii::$app->formatter;
   echo $formatter->asDate(date('Y-m-d'), 'long'),"<br>";
   echo $formatter->asTime(date("Y-m-d")),"<br>";
   echo $formatter->asDatetime(date("Y-m-d")),"<br>";

   echo $formatter->asTimestamp(date("Y-m-d")),"<br>";
   echo $formatter->asRelativeTime(date("Y-m-d")),"<br>";
?>

步驟 5 − 在Web瀏覽器的位址列中輸入https://:8080/index.php?r=site/formatter,您將看到以下輸出。

Formatter Output

日期格式

還有四個日期格式快捷方式:short、medium、long和full

步驟 1 − 以這種方式修改formatter檢視檔案。

<?php
   $formatter = \Yii::$app->formatter;
   echo $formatter->asDate(date('Y-m-d'), 'short'),"<br>";
   echo $formatter->asDate(date('Y-m-d'), 'medium'),"<br>";
   echo $formatter->asDate(date('Y-m-d'), 'long'),"<br>";
   echo $formatter->asDate(date('Y-m-d'), 'full'),"<br>";
?>

步驟 2 − 如果您訪問Web瀏覽器並輸入https://:8080/index.php?r=site/formatter,您將看到以下輸出。

Data Formats Output

數字格式

formatter元件支援以下與數字相關的格式:

輸出格式 示例
integer 51
decimal 105.51
percent 51%
scientific 1.050000E+2
currency $105
size 105 位元組
shortSize 105 B

步驟 1 − 以這種方式修改formatter檢視。

<?php
   $formatter = \Yii::$app->formatter;
   echo Yii::$app->formatter->asInteger(105),"<br>";
   echo Yii::$app->formatter->asDecimal(105.41),"<br>";
   echo Yii::$app->formatter->asPercent(0.51),"<br>";
   echo Yii::$app->formatter->asScientific(105),"<br>";
   echo Yii::$app->formatter->asCurrency(105, "$"),"<br>";
   echo Yii::$app->formatter->asSize(105),"<br>";
   echo Yii::$app->formatter->asShortSize(105),"<br>";
?>

步驟 2 − 訪問https://:8080/index.php?r=site/formatter,您將看到以下輸出。

Number Formats Output

其他格式

Yii還支援其他格式:

  • text − 值將進行HTML編碼。

  • raw − 值將按原樣輸出。

  • paragraphs − 值將格式化為HTML文字段落,幷包裝在p標籤中。

  • ntext − 值將格式化為HTML純文字,其中換行符將轉換為換行符。

  • html − 值將使用HtmlPurifier進行淨化,以避免XSS攻擊。

  • image − 值將格式化為影像標籤。

  • boolean − 值將格式化為布林值。

  • url − 值將格式化為連結。

  • email − 值將格式化為mailto連結。

formatter可能會使用當前活動區域設定來確定如何為特定國家/地區格式化值。

以下示例顯示瞭如何為不同的區域設定格式化日期。

<?php
   Yii::$app->formatter->locale = 'ru-RU';
   echo Yii::$app->formatter->asDate('2016-01-01'); // output: 1 января 2016 г.
   Yii::$app->formatter->locale = 'de-DE';
   // output: 1. Januar 2016
   echo Yii::$app->formatter->asDate('2016-01-01');
   Yii::$app->formatter->locale = 'en-US';
   // output: January 1, 2016
   echo Yii::$app->formatter->asDate('2016-01-01');
?>

Yii - 分頁

當您有太多資料要顯示在一個頁面上時,您應該將其顯示在多個頁面上。這也被稱為分頁。

要顯示分頁的實際操作,我們需要資料。

準備資料庫

步驟 1 − 建立一個新的資料庫。資料庫可以透過以下兩種方式準備。

  • 在終端執行mysql -u root -p

  • 透過CREATE DATABASE helloworld CHARACTER SET utf8 COLLATE utf8_general_ci;建立一個新的資料庫。

步驟 2 − 在config/db.php檔案中配置資料庫連線。以下配置適用於當前使用的系統。

<?php
   return [
      'class' => 'yii\db\Connection',
      'dsn' => 'mysql:host = localhost;dbname = helloworld',
      'username' => 'vladimir',
      'password' => '12345',
      'charset' => 'utf8',
   ];
?>

步驟 3 − 在根資料夾中執行 ./yii migrate/create test_table。此命令將建立一個用於管理我們資料庫的資料庫遷移。遷移檔案應該出現在專案根目錄的migrations資料夾中。

步驟 4 − 以這種方式修改遷移檔案(在本例中為m160106_163154_test_table.php)。

<?php
   use yii\db\Schema;
   use yii\db\Migration;
   class m160106_163154_test_table extends Migration {
      public function safeUp() {
         $this->createTable("user", [
            "id" => Schema::TYPE_PK,
            "name" => Schema::TYPE_STRING,
            "email" => Schema::TYPE_STRING,
         ]);
         $this->batchInsert("user", ["name", "email"], [
            ["User1", "user1@gmail.com"],
            ["User2", "user2@gmail.com"],
            ["User3", "user3@gmail.com"],
            ["User4", "user4@gmail.com"],
            ["User5", "user5@gmail.com"],
            ["User6", "user6@gmail.com"],
            ["User7", "user7@gmail.com"],
            ["User8", "user8@gmail.com"],
            ["User9", "user9@gmail.com"],
            ["User10", "user10@gmail.com"],
            ["User11", "user11@gmail.com"],
         ]);
      }
      public function safeDown() {
         $this->dropTable('user');
      }
   }
?>

以上遷移建立了一個user表,其中包含以下欄位:id、name和email。它還添加了一些演示使用者。

步驟 5 − 在專案根目錄中執行 ./yii migrate以將遷移應用於資料庫。

步驟 6 − 現在,我們需要為我們的user表建立一個模型。為簡單起見,我們將使用Gii程式碼生成工具。開啟此URL:https://:8080/index.php?r=gii。然後,單擊“模型生成器”標題下的“開始”按鈕。填寫表名(“user”)和模型類(“MyUser”),單擊“預覽”按鈕,最後單擊“生成”按鈕。

Create Model

MyUser模型出現在models目錄中。

分頁的實際操作

步驟 1 − 將actionPagination方法新增到SiteController中。

public function actionPagination() {
   //preparing the query
   $query = MyUser::find();
   // get the total number of users
   $count = $query->count();
   //creating the pagination object
   $pagination = new Pagination(['totalCount' => $count, 'defaultPageSize' => 10]);
   //limit the query using the pagination and retrieve the users
   $models = $query->offset($pagination->offset)
      ->limit($pagination->limit)
      ->all();
   return $this->render('pagination', [
      'models' => $models,
      'pagination' => $pagination,
   ]);
}

步驟 2 − 在views/site資料夾中建立一個名為pagination.php的檢視檔案。

<?php
   use yii\widgets\LinkPager;
?>
<?php foreach ($models as $model): ?>
   <?= $model->id; ?>
   <?= $model->name; ?>
   <?= $model->email; ?>
   <br/>
<?php endforeach; ?>
<?php
   // display pagination
   echo LinkPager::widget([
      'pagination' => $pagination,
   ]);
?>

現在,透過Web瀏覽器訪問本地主機https://:8080/index.php?r=site/pagination,您將看到一個分頁小部件:

Pagination Widget

Yii - 排序

在顯示大量資料時,我們通常需要對資料進行排序。Yii使用yii\data\Sort物件來表示排序方案。

要顯示排序的實際操作,我們需要資料。

準備資料庫

步驟 1 − 建立一個新的資料庫。資料庫可以透過以下兩種方式準備。

  • 在終端執行mysql -u root –p

  • 透過CREATE DATABASE helloworld CHARACTER SET utf8 COLLATE utf8_general_ci;建立一個新的資料庫。

步驟 2 − 在config/db.php檔案中配置資料庫連線。以下配置適用於當前使用的系統。

<?php
   return [
      'class' => 'yii\db\Connection',
      'dsn' => 'mysql:host=localhost;dbname=helloworld',
      'username' => 'vladimir',
      'password' => '12345',
      'charset' => 'utf8',
   ];
?>

步驟 3 − 在根資料夾中執行 ./yii migrate/create test_table。此命令將建立一個用於管理我們資料庫的資料庫遷移。遷移檔案應該出現在專案根目錄的migrations資料夾中。

步驟 4 − 以這種方式修改遷移檔案(在本例中為m160106_163154_test_table.php)。

<?php
   use yii\db\Schema;
   use yii\db\Migration;
   class m160106_163154_test_table extends Migration {
      public function safeUp() {
         $this->createTable("user", [
            "id" => Schema::TYPE_PK,
            "name" => Schema::TYPE_STRING,
            "email" => Schema::TYPE_STRING,
         ]);
         $this->batchInsert("user", ["name", "email"], [
            ["User1", "user1@gmail.com"],
            ["User2", "user2@gmail.com"],
            ["User3", "user3@gmail.com"],
            ["User4", "user4@gmail.com"],
            ["User5", "user5@gmail.com"],
            ["User6", "user6@gmail.com"],
            ["User7", "user7@gmail.com"],
            ["User8", "user8@gmail.com"],
            ["User9", "user9@gmail.com"],
            ["User10", "user10@gmail.com"],
            ["User11", "user11@gmail.com"],
         ]);
      }
      public function safeDown() {
         $this->dropTable('user');
      }
   }
?>

以上遷移建立了一個user表,其中包含以下欄位:id、name和email。它還添加了一些演示使用者。

步驟 5 − 在專案根目錄中執行 ./yii migrate以將遷移應用於資料庫。

步驟 6 − 現在,我們需要為我們的user表建立一個模型。為簡單起見,我們將使用Gii程式碼生成工具。開啟此URL:https://:8080/index.php?r=gii。然後,單擊“模型生成器”標題下的“開始”按鈕。填寫表名(“user”)和模型類(“MyUser”),單擊“預覽”按鈕,最後單擊“生成”按鈕。

Preparing DB

MyUser模型應該出現在models目錄中。

排序的實際操作

步驟 1 − 將actionSorting方法新增到SiteController中。

public function actionSorting() {
   //declaring the sort object
   $sort = new Sort([
      'attributes' => ['id', 'name', 'email'], 
   ]);
   //retrieving all users
   $models = MyUser::find()
      ->orderBy($sort->orders)
      ->all();
   return $this->render('sorting', [
      'models' => $models,
      'sort' => $sort,
   ]);
}

步驟 2 − 在views/site資料夾中建立一個名為sorting inside檢視檔案。

<?php
   // display links leading to sort actions
   echo $sort->link('id') . ' | ' . $sort->link('name') . ' | ' . $sort->link('email');
?><br/>
<?php foreach ($models as $model): ?>
   <?= $model->id; ?>
   <?= $model->name; ?>
   <?= $model->email; ?>
   <br/>
<?php endforeach; ?>

步驟 3 − 現在,如果您在Web瀏覽器中輸入https://:8080/index.php?r=site/sorting,您會看到id、name和email欄位是可排序的,如下面的影像所示。

Sorting Action

Yii - 屬性

PHP中的類成員變數也稱為屬性。它們表示類例項的狀態。Yii引入了一個名為yii\base\Object的類。它支援透過gettersetter類方法定義屬性。

getter方法以get開頭。setter方法以set開頭。您可以像使用類成員變數一樣使用由getter和setter定義的屬性。

當讀取屬性時,將呼叫getter方法。當分配屬性時,將呼叫setter方法。如果未定義setter,則由getter定義的屬性為只讀

步驟 1 − 在components資料夾中建立一個名為Taxi.php的檔案。

<?php
   namespace app\components;
   use yii\base\Object;
   class Taxi extends Object {
      private $_phone;
      public function getPhone() {
         return $this->_phone;
      }
      public function setPhone($value) {
         $this->_phone = trim($value);
      }
   }
?>

在上面的程式碼中,我們定義了從Object類派生的Taxi類。我們設定了一個getter – getPhone()和一個setter – setPhone()

步驟 2現在,將actionProperties方法新增到SiteController中。

public function actionProperties() {
   $object = new Taxi();
   // equivalent to $phone = $object->getPhone();
   $phone = $object->phone;
   var_dump($phone);
   // equivalent to $object->setLabel('abc');
   $object->phone = '79005448877';
   var_dump($object);
}

在上面的函式中,我們建立了一個Taxi物件,嘗試透過getter訪問phone屬性,並透過setter設定phone屬性。

步驟 3 − 在您的Web瀏覽器中,輸入https://:8080/index.php?r=site/properties,在位址列中,您應該看到以下輸出。

Properties Output

Yii - 資料提供者

Yii提供了一組資料提供程式類,它們封裝了分頁和排序。資料提供程式實現yii\data\DataProviderInterface。它支援檢索排序和分頁的資料。資料提供程式通常與資料小部件一起使用。

Yii包含:

  • ActiveDataProvider − 使用yii\db\ActiveQueryyii\db\Query從資料庫查詢資料。

  • SqlDataProvider − 執行SQL並返回資料作為陣列。

  • ArrayDataProvider − 獲取一個大陣列並返回其中的一部分。

您可以透過配置其paginationsort屬性來定義資料提供程式的排序和分頁行為。資料小部件(例如yii\grid\GridView)具有一個名為dataProvider的屬性,該屬性接受資料提供程式例項並在螢幕上顯示資料。

準備資料庫

步驟 1 − 建立一個新的資料庫。資料庫可以透過以下兩種方式準備。

  • 在終端執行mysql -u root –p

  • 透過CREATE DATABASE helloworld CHARACTER SET utf8 COLLATE utf8_general_ci;建立一個新的資料庫。

步驟 2 − 在config/db.php檔案中配置資料庫連線。以下配置適用於當前使用的系統。

<?php
   return [
      'class' => 'yii\db\Connection',
      'dsn' => 'mysql:host = localhost;dbname = helloworld',
      'username' => 'vladimir',
      'password' => '12345',
      'charset' => 'utf8',
   ];
?>

步驟 3 − 在根資料夾中執行 ./yii migrate/create test_table。此命令將建立一個用於管理我們資料庫的資料庫遷移。遷移檔案應該出現在專案根目錄的migrations資料夾中。

步驟 4 − 以這種方式修改遷移檔案(在本例中為m160106_163154_test_table.php)。

<?php
   use yii\db\Schema;
   use yii\db\Migration;
   class m160106_163154_test_table extends Migration {
      public function safeUp() {
         $this->createTable("user", [
            "id" => Schema::TYPE_PK,
            "name" => Schema::TYPE_STRING,
            "email" => Schema::TYPE_STRING,
         ]);
         $this->batchInsert("user", ["name", "email"], [
            ["User1", "user1@gmail.com"],
            ["User2", "user2@gmail.com"],
            ["User3", "user3@gmail.com"],
            ["User4", "user4@gmail.com"],
            ["User5", "user5@gmail.com"],
            ["User6", "user6@gmail.com"],
            ["User7", "user7@gmail.com"],
            ["User8", "user8@gmail.com"],
            ["User9", "user9@gmail.com"],
            ["User10", "user10@gmail.com"],
            ["User11", "user11@gmail.com"],
         ]);
      }
      public function safeDown() {
         $this->dropTable('user');
      }
   }
?>

以上遷移建立了一個user表,其中包含以下欄位:id、name和email。它還添加了一些演示使用者。

步驟 5 − 在專案根目錄中執行 ./yii migrate以將遷移應用於資料庫。

步驟 6 − 現在,我們需要為我們的user表建立一個模型。為簡單起見,我們將使用Gii程式碼生成工具。開啟此URL:https://:8080/index.php?r=gii。然後,單擊“模型生成器”標題下的“開始”按鈕。填寫表名(“user”)和模型類(“MyUser”),單擊“預覽”按鈕,最後單擊“生成”按鈕。

Generate Button

MyUser模型應該出現在models目錄中。

活動資料提供程式

步驟 1 − 在SiteController中建立一個名為actionDataProvider的函式。

public function actionDataProvider(){
   $query = MyUser::find();
   $provider = new ActiveDataProvider([
      'query' => $query,
      'pagination' => [
         'pageSize' => 2,
      ],
   ]);
   // returns an array of users objects
   $users = $provider->getModels();
   var_dump($users);
}

在上面的程式碼中,我們定義了一個ActiveDataProvider類的例項,並顯示第一頁的使用者。yii\data\ActiveDataProvider類使用DB應用程式元件作為DB連線。

步驟 2 − 如果您輸入本地主機地址https://:8080/index.php?r=site/dataprovider,您將看到以下輸出。

Active Data Provider

SQL資料提供程式

yii\data\SqlDataProvider類與原始SQL語句一起使用。

步驟 1 − 以這種方式修改actionDataProvider方法。

public function actionDataProvider() {
   $count = Yii::$app->db->createCommand('SELECT COUNT(*) FROM user')->queryScalar();
   $provider = new SqlDataProvider([
      'sql' => 'SELECT * FROM user',
      'totalCount' => $count,
      'pagination' => [
         'pageSize' => 5,
      ],
      'sort' => [
         'attributes' => [
            'id',
            'name',
            'email',
         ],
      ],
   ]);
   // returns an array of data rows
   $users = $provider->getModels();
   var_dump($users);
}

步驟 2 − 在Web瀏覽器的位址列中輸入https://:8080/index.php?r=site/data-provider,您將看到以下輸出。

SQL Data Provider Output

陣列資料提供程式

yii\data\ArrayDataProvider類最適合處理大型陣列。此陣列中的元素可以是DAO或Active Record例項的查詢結果。

步驟 1 − 以這種方式修改actionDataProvider方法。

public function actionDataProvider() {
   $data = MyUser::find()->asArray()->all();
   $provider = new ArrayDataProvider([
      'allModels' => $data,
      'pagination' => [
         'pageSize' => 3,
      ],
      'sort' => [
         'attributes' => ['id', 'name'],
      ],
   ]);
   // get the rows in the currently requested page
   $users = $provider->getModels();
   var_dump($users);
}

步驟 2 − 如果您透過Web瀏覽器訪問地址https://:8080/index.php?r=site/data-provider,您將看到以下輸出。

Array Data Provider Output

請注意,與SQL資料提供程式和活動資料提供程式不同,陣列資料提供程式將所有資料載入到記憶體中,因此效率較低。

Yii - 資料小部件

Yii提供了一組用於顯示資料的小部件。您可以使用DetailView小部件顯示單個記錄。ListView小部件以及GridView可用於顯示具有過濾、排序和分頁等功能的記錄表。

準備資料庫

步驟 1 − 建立一個新的資料庫。資料庫可以透過以下兩種方式準備。

  • 在終端執行mysql -u root –p

  • 透過CREATE DATABASE helloworld CHARACTER SET utf8 COLLATE utf8_general_ci;建立一個新的資料庫。

步驟 2 − 在config/db.php檔案中配置資料庫連線。以下配置適用於當前使用的系統。

<?php
   return [
      'class' => 'yii\db\Connection',
      'dsn' => 'mysql:host=localhost;dbname=helloworld',
      'username' => 'vladimir',
      'password' => '12345',
      'charset' => 'utf8',
   ];
?>

步驟 3 − 在根資料夾中執行 ./yii migrate/create test_table。此命令將建立一個用於管理我們資料庫的資料庫遷移。遷移檔案應該出現在專案根目錄的migrations資料夾中。

步驟 4 − 以這種方式修改遷移檔案(在本例中為m160106_163154_test_table.php)。

<?php
   use yii\db\Schema;
   use yii\db\Migration;
   class m160106_163154_test_table extends Migration {
      public function safeUp() {
         $this->createTable("user", [
            "id" => Schema::TYPE_PK,
            "name" => Schema::TYPE_STRING,
            "email" => Schema::TYPE_STRING,
         ]);
         $this->batchInsert("user", ["name", "email"], [
            ["User1", "user1@gmail.com"],
            ["User2", "user2@gmail.com"],
            ["User3", "user3@gmail.com"],
            ["User4", "user4@gmail.com"],
            ["User5", "user5@gmail.com"],
            ["User6", "user6@gmail.com"],
            ["User7", "user7@gmail.com"],
            ["User8", "user8@gmail.com"],
            ["User9", "user9@gmail.com"],
            ["User10", "user10@gmail.com"],
            ["User11", "user11@gmail.com"],
         ]);
      }
      public function safeDown() {
         $this->dropTable('user');
      }
   }
?>

以上遷移建立了一個user表,其中包含以下欄位:id、name和email。它還添加了一些演示使用者。

步驟 5 − 在專案根目錄中執行 ./yii migrate以將遷移應用於資料庫。

步驟 6 − 現在,我們需要為我們的user表建立一個模型。為簡單起見,我們將使用Gii程式碼生成工具。開啟此URL:https://:8080/index.php?r=gii。然後,單擊“模型生成器”標題下的“開始”按鈕。填寫表名(“user”)和模型類(“MyUser”),單擊“預覽”按鈕,最後單擊“生成”按鈕。

Data Widget Preparing DB

MyUser模型應該出現在models目錄中。

DetailView小部件

DetailView小部件顯示單個模型的資料。$attributes屬性定義了要顯示哪些模型屬性。

步驟 1 − 將actionDataWidget方法新增到SiteController中。

public function actionDataWidget() {
   $model = MyUser::find()->one();
   return $this->render('datawidget', [
      'model' => $model
   ]);
}

在上面的程式碼中,我們找到第一個MyUser模型並將其傳遞給datawidget檢視。

步驟 2 − 在views/site資料夾中建立一個名為datawidget.php的檔案。

<?php
   use yii\widgets\DetailView;
   echo DetailView::widget([
      'model' => $model,
      'attributes' => [
         'id',
         //formatted as html
         'name:html',
         [
            'label' => 'e-mail',
            'value' => $model->email,
         ],
      ],
   ]);
?>

步驟 3 − 如果您訪問https://:8080/index.php?r=site/data-widget,您將看到DetailView小部件的典型用法。

DetailView Widget

Yii - ListView 小部件

ListView小部件使用資料提供程式來顯示資料。每個模型都使用指定的檢視檔案進行渲染。

步驟 1 − 以這種方式修改actionDataWidget()方法。

public function actionDataWidget() {
   $dataProvider = new ActiveDataProvider([
      'query' => MyUser::find(),
      'pagination' => [
         'pageSize' => 20,
      ],
   ]);
   return $this->render('datawidget', [
      'dataProvider' => $dataProvider
   ]);
}

在上面的程式碼中,我們建立了一個數據提供程式並將其傳遞給datawidget檢視。

步驟 2 − 以這種方式修改datawidget檢視檔案。

<?php
   use yii\widgets\ListView;
   echo ListView::widget([
      'dataProvider' => $dataProvider,
      'itemView' => '_user',
   ]);
?>

我們渲染ListView小部件。每個模型都在_user檢視中渲染。

步驟 3 − 在views/site資料夾中建立一個名為_user.php的檔案。

<?php
   use yii\helpers\Html;
   use yii\helpers\HtmlPurifier;
?>
<div class = "user">
   <?= $model->id ?>
   <?= Html::encode($model->name) ?>
   <?= HtmlPurifier::process($model->email) ?>
</div>

步驟 4 − 在Web瀏覽器的位址列中輸入https://:8080/index.php?r=site/data-widget,您將看到以下內容。

ListView Widget Example Output

Yii - GridView 小部件

GridView小部件從資料提供程式獲取資料,並以表格形式呈現資料。表的每一行表示單個數據項,而每一列表示該項的一個屬性。

步驟 1 − 以這種方式修改datawidget檢視。

<?php
   use yii\grid\GridView;
   echo GridView::widget([
      'dataProvider' => $dataProvider,
   ]);
?>

步驟 2 − 訪問https://:8080/index.php?r=site/data-widget,您將看到DataGrid小部件的典型用法。

DataGrid widget

DataGrid 小部件的列是根據yii\grid\Column 類配置的。它表示模型屬性,並且可以進行過濾和排序。

步驟 3 - 要向網格新增自定義列,請按以下方式修改datawidget檢視。

<?php
   yii\grid\GridView;
   echo GridView::widget([
      'dataProvider' => $dataProvider,
      'columns' => [
         'id',
         [
            'class' => 'yii\grid\DataColumn', // can be omitted, as it is the default
            'label' => 'Name and email',
            'value' => function ($data) {
               return $data->name . " writes from " . $data->email;
            },
         ],
      ],
   ]);
?>

步驟 4 - 如果您訪問地址https://:8080/index.php?r=site/data-widget,您將看到如下所示的輸出。

DataGrid view

可以使用不同的列類(如 yii\grid\SerialColumn、yii\grid\ActionColumn 和 yii\grid\CheckboxColumn)來自定義網格列。

步驟 5 - 請按以下方式修改datawidget檢視。

<?php
   use yii\grid\GridView;
   echo GridView::widget([
      'dataProvider' => $dataProvider,
      'columns' => [
         ['class' => 'yii\grid\SerialColumn'], 'name',
         ['class' => 'yii\grid\ActionColumn'],
         ['class' => 'yii\grid\CheckboxColumn'],
      ],
   ]);
?>

步驟 6 - 訪問https://:8080/index.php?r=site/data-widget,您將看到以下內容。

Modified DataGrid view

Yii - 事件

您可以使用事件在某些執行點注入自定義程式碼。您可以將自定義程式碼附加到事件,當事件被觸發時,程式碼將被執行。例如,當新使用者在您的網站上註冊時,日誌記錄器物件可能會觸發userRegistered事件。如果某個類需要觸發事件,則應從 yii\base\Component 類擴充套件它。

事件處理程式是一個 PHP 回撥函式。您可以使用以下回調函式 -

  • 以字串形式指定的全域性 PHP 函式。

  • 匿名函式。

  • 類名和方法的陣列(以字串形式),例如 ['ClassName', 'methodName']

  • 物件和方法的陣列(以字串形式),例如 [$obj, 'methodName']

步驟 1 - 要將處理程式附加到事件,您應該呼叫yii\base\Component::on()方法。

$obj = new Obj;
// this handler is a global function
$obj->on(Obj::EVENT_HELLO, 'function_name');
// this handler is an object method
$obj->on(Obj::EVENT_HELLO, [$object, 'methodName']);
// this handler is a static class method
$obj->on(Obj::EVENT_HELLO, ['app\components\MyComponent', 'methodName']);
// this handler is an anonymous function

$obj->on(Obj::EVENT_HELLO, function ($event) {
   // event handling logic
});

您可以將一個或多個處理程式附加到事件。附加的處理程式將按照它們附加到事件的順序呼叫。

步驟 2 - 要停止處理程式的呼叫,您應該將yii\base\Event::$handled 屬性設定為true

$obj->on(Obj::EVENT_HELLO, function ($event) {
   $event->handled = true;
});

步驟 3 - 要在佇列的開頭插入處理程式,您可以呼叫yii\base\Component::on(),並將第四個引數傳遞為 false。

$obj->on(Obj::EVENT_HELLO, function ($event) {
   // ...
}, $data, false);

步驟 4 - 要觸發事件,請呼叫yii\base\Component::trigger()方法。

namespace app\components;
use yii\base\Component;
use yii\base\Event;
class Obj extends Component {
   const EVENT_HELLO = 'hello';
   public function triggerEvent() {
      $this->trigger(self::EVENT_HELLO);
   }
}

步驟 5 - 要從事件中分離處理程式,您應該呼叫yii\base\Component::off()方法。

$obj = new Obj;
// this handler is a global function
$obj->off(Obj::EVENT_HELLO, 'function_name');
// this handler is an object method
$obj->off(Obj::EVENT_HELLO, [$object, 'methodName']);
// this handler is a static class method
$obj->off(Obj::EVENT_HELLO, ['app\components\MyComponent', 'methodName']);
// this handler is an anonymous function

$obj->off(Obj::EVENT_HELLO, function ($event) {
   // event handling logic
});

Yii - 建立事件

在本章中,我們將瞭解如何在 Yii 中建立事件。為了展示事件的實際應用,我們需要資料。

準備資料庫

步驟 1 − 建立一個新的資料庫。資料庫可以透過以下兩種方式準備。

  • 在終端執行mysql -u root –p

  • 透過CREATE DATABASE helloworld CHARACTER SET utf8 COLLATE utf8_general_ci;建立一個新的資料庫。

步驟 2 − 在config/db.php檔案中配置資料庫連線。以下配置適用於當前使用的系統。

<?php
   return [
      'class' => 'yii\db\Connection',
      'dsn' => 'mysql:host=localhost;dbname=helloworld',
      'username' => 'vladimir',
      'password' => '12345',
      'charset' => 'utf8',
   ];
?>

步驟 3 − 在根資料夾中執行 ./yii migrate/create test_table。此命令將建立一個用於管理我們資料庫的資料庫遷移。遷移檔案應該出現在專案根目錄的migrations資料夾中。

步驟 4 − 以這種方式修改遷移檔案(在本例中為m160106_163154_test_table.php)。

<?php
   use yii\db\Schema;
   use yii\db\Migration;
   class m160106_163154_test_table extends Migration {
      public function safeUp() {
         $this->createTable("user", [
            "id" => Schema::TYPE_PK,
            "name" => Schema::TYPE_STRING,
            "email" => Schema::TYPE_STRING,
         ]);
         $this->batchInsert("user", ["name", "email"], [
            ["User1", "user1@gmail.com"],
            ["User2", "user2@gmail.com"],
            ["User3", "user3@gmail.com"],
            ["User4", "user4@gmail.com"],
            ["User5", "user5@gmail.com"],
            ["User6", "user6@gmail.com"],
            ["User7", "user7@gmail.com"],
            ["User8", "user8@gmail.com"],
            ["User9", "user9@gmail.com"],
            ["User10", "user10@gmail.com"],
            ["User11", "user11@gmail.com"],
         ]);
      }
      public function safeDown() {
         $this->dropTable('user');
      }
   }
?>

以上遷移建立了一個user表,其中包含以下欄位:id、name和email。它還添加了一些演示使用者。

步驟 5 − 在專案根目錄中執行 ./yii migrate以將遷移應用於資料庫。

步驟 6 − 現在,我們需要為我們的user表建立一個模型。為簡單起見,我們將使用Gii程式碼生成工具。開啟此URL:https://:8080/index.php?r=gii。然後,單擊“模型生成器”標題下的“開始”按鈕。填寫表名(“user”)和模型類(“MyUser”),單擊“預覽”按鈕,最後單擊“生成”按鈕。

Creating Event Preparing DB

MyUser模型應該出現在models目錄中。

建立事件

假設我們希望在每次新使用者註冊到我們的網站時向管理員傳送電子郵件。

步驟 1 - 請按以下方式修改models/MyUser.php檔案。

<?php
   namespace app\models;
   use Yii;
   /**
   * This is the model class for table "user".
   *
   * @property integer $id
   * @property string $name
   * @property string $email
   */
   class MyUser extends \yii\db\ActiveRecord {
      const EVENT_NEW_USER = 'new-user';
      public function init() {
         // first parameter is the name of the event and second is the handler.
         $this->on(self::EVENT_NEW_USER, [$this, 'sendMailToAdmin']);
      }
      /**
      * @inheritdoc
      */
      public static function tableName() {
         return 'user';
      }
      /**
      * @inheritdoc
      */
      public function rules() {
         return [
            [['name', 'email'], 'string', 'max' => 255]
         ];
      }
      /**
      * @inheritdoc
      */
      public function attributeLabels() {
         return [
            'id' => 'ID',
            'name' => 'Name',
            'email' => 'Email',
         ];
      }
      public function sendMailToAdmin($event) {
         echo 'mail sent to admin using the event';
      }
   }
?>

在上面的程式碼中,我們定義了一個“new-user”事件。然後,在 init() 方法中,我們將sendMailToAdmin函式附加到“new-user”事件。現在,我們需要觸發此事件。

步驟 2 - 在 SiteController 中建立一個名為actionTestEvent的方法。

public function actionTestEvent() {
   $model = new MyUser();
   $model->name = "John";
   $model->email = "john@gmail.com";
   if($model->save()) {
      $model->trigger(MyUser::EVENT_NEW_USER);
   }
}

在上面的程式碼中,我們建立了一個新使用者並觸發了“new-user”事件。

步驟 3 - 現在鍵入https://:8080/index.php?r=site/test-event,您將看到以下內容。

Creating Event

Yii - 行為

行為是 yii\base\Behavior 類的例項。行為將其方法和屬性注入到它所附加的元件中。行為還可以響應元件觸發的事件。

步驟 1 - 要定義行為,請擴充套件yii\base\Behavior類。

namespace app\components;
use yii\base\Behavior;
class MyBehavior extends Behavior {
   private $_prop1;
   public function getProp1() {
      return $this->_prop1;
   }
   public function setProp1($value) {
      $this->_prop1 = $value;
   }
   public function myFunction() {
      // ...
   }
}

上面的程式碼定義了一個行為,它具有一個屬性 (prop1) 和一個方法 (myFunction)。當此行為附加到元件時,該元件也將具有prop1屬性和myFunction方法。

要訪問行為附加到的元件,您可以使用yii\base\Behavior::$owner 屬性

步驟 2 - 如果您希望行為響應元件事件,則應覆蓋yii\base\Behavior::events()方法。

namespace app\components;
use yii\db\ActiveRecord;
use yii\base\Behavior;
class MyBehavior extends Behavior {
   public function events() {
      return [
         ActiveRecord::EVENT_AFTER_VALIDATE => 'afterValidate',
      ];
   }
   public function afterValidate($event) {
      // ...
   }
}

步驟 3 - 要附加行為,您應該覆蓋元件類的behaviors()方法。

namespace app\models;
use yii\db\ActiveRecord;
use app\components\MyBehavior;
class MyUser extends ActiveRecord {
   public function behaviors() {
      return [
         // anonymous behavior, behavior class name only
         MyBehavior::className(),
         // named behavior, behavior class name only
         'myBehavior2' => MyBehavior::className(),
         // anonymous behavior, configuration array
         [
            'class' => MyBehavior::className(),
            'prop1' => 'value1',
            'prop2' => 'value2',
            'prop3' => 'value3',
         ],
         // named behavior, configuration array
         'myBehavior4' => [
            'class' => MyBehavior::className(),
            'prop1' => 'value1'
         ]
      ];
   }
}

步驟 4 - 要分離行為,請呼叫yii\base\Component::detachBehavior()方法。

$component->detachBehavior('myBehavior');

為了展示行為的實際應用,我們需要資料。

準備資料庫

步驟 1 − 建立一個新的資料庫。資料庫可以透過以下兩種方式準備。

  • 在終端執行mysql -u root –p

  • 透過CREATE DATABASE helloworld CHARACTER SET utf8 COLLATE utf8_general_ci;建立一個新的資料庫。

步驟 2 − 在config/db.php檔案中配置資料庫連線。以下配置適用於當前使用的系統。

<?php
   return [
      'class' => 'yii\db\Connection',
      'dsn' => 'mysql:host = localhost;dbname = helloworld',
      'username' => 'vladimir',
      'password' => '12345',
      'charset' => 'utf8',
   ];
?>

步驟 3 − 在根資料夾中執行 ./yii migrate/create test_table。此命令將建立一個用於管理我們資料庫的資料庫遷移。遷移檔案應該出現在專案根目錄的migrations資料夾中。

步驟 4 − 以這種方式修改遷移檔案(在本例中為m160106_163154_test_table.php)。

<?php
   use yii\db\Schema;
   use yii\db\Migration;
   class m160106_163154_test_table extends Migration {
      public function safeUp() {
         $this->createTable("user", [
            "id" => Schema::TYPE_PK,
            "name" => Schema::TYPE_STRING,
            "email" => Schema::TYPE_STRING,
         ]);
         $this->batchInsert("user", ["name", "email"], [
            ["User1", "user1@gmail.com"],
            ["User2", "user2@gmail.com"],
            ["User3", "user3@gmail.com"],
            ["User4", "user4@gmail.com"],
            ["User5", "user5@gmail.com"],
            ["User6", "user6@gmail.com"],
            ["User7", "user7@gmail.com"],
            ["User8", "user8@gmail.com"],
            ["User9", "user9@gmail.com"],
            ["User10", "user10@gmail.com"],
            ["User11", "user11@gmail.com"],
         ]);
      }
      public function safeDown() {
         $this->dropTable('user');
      }
   }
?>

以上遷移建立了一個user表,其中包含以下欄位:id、name和email。它還添加了一些演示使用者。

步驟 5 - 在專案根目錄中執行 ./yii migrate以將遷移應用到資料庫。

步驟 6 - 現在,我們需要為我們的user 表建立一個模型。為簡單起見,我們將使用Gii程式碼生成工具。開啟此URL:https://:8080/index.php?r=gii。然後,單擊“模型生成器”標題下的“開始”按鈕。填寫表名(“user”)和模型類(“MyUser”),單擊“預覽”按鈕,最後單擊“生成”按鈕。

Behaviors Preparing DB

MyUser模型應該出現在models目錄中。

Yii - 建立行為

假設我們希望建立一個行為,該行為將行為附加到的元件的“name”屬性大寫。

步驟 1 - 在 components 資料夾中,建立一個名為UppercaseBehavior.php的檔案,其中包含以下程式碼。

<?php
   namespace app\components;
   use yii\base\Behavior;
   use yii\db\ActiveRecord;
   class UppercaseBehavior extends Behavior {
      public function events() {
         return [
            ActiveRecord::EVENT_BEFORE_VALIDATE => 'beforeValidate',
         ];
      }
      public function beforeValidate($event) {
         $this->owner->name = strtoupper($this->owner->name);
     }
   }
?>

在上面的程式碼中,我們建立了UppercaseBehavior,它在觸發“beforeValidate”事件時將 name 屬性大寫。

步驟 2 - 要將此行為附加到MyUser模型,請按以下方式修改它。

<?php
   namespace app\models;
   use app\components\UppercaseBehavior;
   use Yii;
   /**
   * This is the model class for table "user".
   *
   * @property integer $id
   * @property string $name
   * @property string $email
   */
   class MyUser extends \yii\db\ActiveRecord {
      public function behaviors() {
         return [
            // anonymous behavior, behavior class name only
            UppercaseBehavior::className(),
         ];
      }
      /**
      * @inheritdoc
      */
      public static function tableName() {
         return 'user';
      }
      /**
      * @inheritdoc
      */
      public function rules() {
         return [
            [['name', 'email'], 'string', 'max' => 255]
         ];
      }
      /**
      * @inheritdoc
      */
      public function attributeLabels() {
         return [
            'id' => 'ID',
            'name' => 'Name',
            'email' => 'Email',
         ];
      }
   }

現在,無論何時建立或更新使用者,其 name 屬性都將大寫。

步驟 3 - 向SiteController新增一個actionTestBehavior函式。

public function actionTestBehavior() {
   //creating a new user
   $model = new MyUser();
   $model->name = "John";
   $model->email = "john@gmail.com";
   if($model->save()){
      var_dump(MyUser::find()->asArray()->all());
   }
}

步驟 4 - 在位址列中鍵入https://:8080/index.php?r=site/test-behavior,您將看到新建立的MyUser模型的name屬性大寫。

UppercaseBehavior

Yii - 配置

配置用於建立新物件或初始化現有物件。配置通常包含類名和初始值列表。它們還可以包含事件處理程式和行為列表。

以下是資料庫配置示例 -

<?php
   $config = [
      'class' => 'yii\db\Connection',
      'dsn' => 'mysql:host = localhost;dbname = helloworld',
      'username' => 'vladimir',
      'password' => '12345',
      'charset' => 'utf8',
   ];
   $db = Yii::createObject($config);
?>

Yii::createObject()方法接受一個配置陣列,並根據配置中命名的類建立一個物件。

配置的格式 -

[
   //a fully qualified class name for the object being created
   'class' => 'ClassName',
   //initial values for the named property
   'propertyName' => 'propertyValue',
   //specifies what handlers should be attached to the object's events
   'on eventName' => $eventHandler,
   //specifies what behaviors should be attached to the object
   'as behaviorName' => $behaviorConfig,
]

基本應用程式模板的配置檔案是最複雜的之一 -

<?php
   $params = require(__DIR__ . '/params.php');
   $config = [
      'id' => 'basic',
      'basePath' => dirname(__DIR__),
      'bootstrap' => ['log'],
      'components' => [
         'request' => [
            // !!! insert a secret key in the following (if it is empty) - this 
               //is required by cookie validation
            'cookieValidationKey' => 'ymoaYrebZHa8gURuolioHGlK8fLXCKjO',
         ],
         'cache' => [
            'class' => 'yii\caching\FileCache',
         ],
         'user' => [
            'identityClass' => 'app\models\User',
            'enableAutoLogin' => true,
         ],
         'errorHandler' => [
            'errorAction' => 'site/error',
         ],
         'mailer' => [
            'class' => 'yii\swiftmailer\Mailer',
            // send all mails to a file by default. You have to set
            // 'useFileTransport' to false and configure a transport
            // for the mailer to send real emails.
            'useFileTransport' => true,
         ],
         'log' => [
            'traceLevel' => YII_DEBUG ? 3 : 0,
            'targets' => [
               [
                  'class' => 'yii\log\FileTarget',
                  'levels' => ['error', 'warning'],
               ],
            ],
         ],
         'urlManager' => [
            //'showScriptName' => false,
            //'enablePrettyUrl' => true,
            //'enableStrictParsing' => true,
            //'suffix' => '/'
         ],
         'db' => require(__DIR__ . '/db.php'),
      ],
      'modules' => [
         'hello' => [
            'class' => 'app\modules\hello\Hello',
         ],
      ],
      'params' => $params,
   ];
   if (YII_ENV_DEV) {
      // configuration adjustments for 'dev' environment
      $config['bootstrap'][] = 'debug';
      $config['modules']['debug'] = [
         'class' => 'yii\debug\Module',
      ];
      $config['bootstrap'][] = 'gii';
      $config['modules']['gii'] = [
         'class' => 'yii\gii\Module',
      ];
   }
   return $config;
?>

在上面的配置檔案中,我們沒有定義類名。這是因為我們已經在index.php檔案中定義了它 -

<?php
   //defining global constans
   defined('YII_DEBUG') or define('YII_DEBUG', true);
   defined('YII_ENV') or define('YII_ENV', 'dev');
   //register composer autoloader
   require(__DIR__ . '/../vendor/autoload.php');
   //include yii files
   require(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php');
   //load application config
   $config = require(__DIR__ . '/../config/web.php');
   //create, config, and process request
   (new yii\web\Application($config))->run();
?>

許多小部件也使用配置,如下面的程式碼所示。

<?php
   NavBar::begin([
      'brandLabel' => 'My Company',
      'brandUrl' => Yii::$app->homeUrl,
      'options' => [
         'class' => 'navbar-inverse navbar-fixed-top',
      ],
   ]);
   echo Nav::widget([
      'options' => ['class' => 'navbar-nav navbar-right'],
      'items' => [
         ['label' => 'Home', 'url' => ['/site/index']],
         ['label' => 'About', 'url' => ['/site/about']],
         ['label' => 'Contact', 'url' => ['/site/contact']],
         Yii::$app->user->isGuest ?
         ['label' => 'Login', 'url' => ['/site/login']] :
         [
            'label' => 'Logout (' . Yii::$app->user->identity->username . ')',
            'url' => ['/site/logout'],
            'linkOptions' => ['data-method' => 'post']
         ],
      ],
   ]);
   NavBar::end();
?>

當配置過於複雜時,一種常見的做法是建立一個 PHP 檔案,該檔案返回一個數組。請檢視config/console.php配置檔案 -

<?php
   Yii::setAlias('@tests', dirname(__DIR__) . '/tests');

   $params = require(__DIR__ . '/params.php');
   $db = require(__DIR__ . '/db.php');

   return [
      'id' => 'basic-console',
      'basePath' => dirname(__DIR__),
      'bootstrap' => ['log', 'gii'],
      'controllerNamespace' => 'app\commands',
      'modules' => [
         'gii' => 'yii\gii\Module',
      ],
      'components' => [
         'cache' => [
            'class' => 'yii\caching\FileCache',
         ],
         'log' => [
            'targets' => [
               [
                  'class' => 'yii\log\FileTarget',
                  'levels' => ['error', 'warning'],
               ],
            ],
         ],
         'db' => $db,
      ],
      'params' => $params,
   ];
?>

可以透過呼叫Yii::$container->set()方法來指定預設配置。它允許您在透過Yii::createObject()方法呼叫指定類的所有例項時,為它們應用預設配置。

例如,要自定義yii\widgets\LinkPager類,以便所有連結分頁器最多顯示三個按鈕,您可以使用以下程式碼。

\Yii::$container->set('yii\widgets\LinkPager', [
   'maxButtonCount' => 3,
]);

Yii - 依賴注入

DI(依賴注入)容器是一個知道如何例項化和配置物件的容器。Yii 透過yii\di\Container 類提供 DI 容器。

它支援以下型別的 DI -

  • Setter 和屬性注入
  • PHP 可呼叫注入
  • 建構函式注入
  • 控制器操作注入

DI 容器在型別提示的幫助下支援建構函式注入 -

class Object1 {
   public function __construct(Object2 $object2) {

   }
}
$object1 = $container->get('Object1');
// which is equivalent to the following:
$object2 = new Object2;
$object1 = new Object1($object2);

屬性和 setter 注入透過配置支援 -

<?php
   use yii\base\Object;
   class MyObject extends Object {
      public $var1;
      private $_var2;
      public function getVar2() {
         return $this->_var2;
      }
      public function setVar2(MyObject2 $var2) {
         $this->_var2 = $var2;
      }
   }
   $container->get('MyObject', [], [
      'var1' => $container->get('MyOtherObject'),
      'var2' => $container->get('MyObject2'),
   ]);
?>

在 PHP 可呼叫注入的情況下,容器將使用註冊的 PHP 回撥函式來構建類的新的例項 -

$container->set('Object1', function () {
   $object1 = new Object1(new Object2);
   return $object1;
});
$object1 = $container->get('Object1');

控制器操作注入是一種 DI 型別,其中依賴項使用型別提示宣告。它有助於保持 MVC 控制器精簡輕量級和精簡 -

public function actionSendToAdmin(EmailValidator $validator, $email) {
   if ($validator->validate($email)) {
      // sending email
   }
}

您可以使用yii\db\Container::set()方法註冊依賴項 -

<?php
   $container = new \yii\di\Container;
   // register a class name as is. This can be skipped.
   $container->set('yii\db\Connection');
   // register an alias name. You can use $container->get('MyObject')
   // to create an instance of Connection
   $container->set('MyObject', 'yii\db\Connection');
   // register an interface
   // When a class depends on the interface, the corresponding class
   // will be instantiated as the dependent object
   $container->set('yii\mail\MailInterface', 'yii\swiftmailer\Mailer');
   // register an alias name with class configuration
   // In this case, a "class" element is required to specify the class
   $container->set('db', [
      'class' => 'yii\db\Connection',
      'dsn' => 'mysql:host=127.0.0.1;dbname = helloworld',
      'username' => 'vladimir',
      'password' => '12345',
      'charset' => 'utf8',
   ]);
   // register a class with configuration. The configuration
   // will be applied when the class is instantiated by get()
   $container->set('yii\db\Connection', [
      'dsn' => 'mysql:host=127.0.0.1;dbname = helloworld',
      'username' => 'vladimir',
      'password' => '12345',
      'charset' => 'utf8',
   ]);
   // register a PHP callable
   // The callable will be executed each time when $container->get('db') is called
   $container->set('db', function ($container, $params, $config) {
      return new \yii\db\Connection($config);
   });
   // register a component instance
   // $container->get('pageCache') will return the same instance each time when it 
      //is called
   $container->set('pageCache', new FileCache);
?>

使用 DI

步驟 1 - 在components資料夾中,建立一個名為MyInterface.php的檔案,其中包含以下程式碼。

<?php
   namespace app\components;
   interface MyInterface {
      public function test();
   }
?>

步驟 2 - 在 components 資料夾中,建立兩個檔案。

First.php -

<?php
   namespace app\components;
   use app\components\MyInterface;
   class First implements MyInterface {
      public function test() {
         echo "First class <br>";
      }
   }
?>

Second.php -

<?php
   app\components;
   use app\components\MyInterface;
      class Second implements MyInterface {
      public function test() {
         echo "Second class <br>";
      }
   }
?>

步驟 3 - 現在,向 SiteController 新增一個actionTestInterface

public function actionTestInterface() {
   $container = new \yii\di\Container();
   $container->set
      ("\app\components\MyInterface","\app\components\First");
   $obj = $container->get("\app\components\MyInterface");
   $obj->test(); // print "First class"
   $container->set
      ("\app\components\MyInterface","\app\components\Second");
   $obj = $container->get("\app\components\MyInterface");
   $obj->test(); // print "Second class"
}

步驟 4 - 訪問https://:8080/index.php?r=site/test-interface,您應該會看到以下內容。

Using DI

這種方法很方便,因為我們可以在一個地方設定類,其他程式碼將自動使用新類。

Yii - 資料庫訪問

Yii DAO(資料庫訪問物件)提供了一個用於訪問資料庫的 API。它也是其他資料庫訪問方法的基礎:活動記錄和查詢構建器。

Yii DAO 支援以下資料庫 -

  • MySQL
  • MSSQL
  • SQLite
  • MariaDB
  • PostgreSQL
  • ORACLE
  • CUBRID

建立資料庫連線

步驟 1 - 要建立資料庫連線,您需要建立 yii\db\Connection 類的例項。

$mydb = new yii\db\Connection([
   'dsn' => 'mysql:host=localhost;dbname=mydb',
   'username' => 'username',
   'password' => 'password',
   'charset' => 'utf8',
]);

一種常見的做法是在應用程式元件中配置 DB 連線。例如,在基本應用程式模板中,DB 連線配置位於config/db.php檔案中,如下面的程式碼所示。

<?php
   return [
      'class' => 'yii\db\Connection',
      'dsn' => 'mysql:host = localhost;dbname = helloworld',
      'username' => 'vladimir',
      'password' => '123574896',
      'charset' => 'utf8',
   ];
?>

步驟 2 - 要訪問 DB 連線,您可以使用此表示式。

Yii::$app->db

要配置 DB 連線,您應該透過dsn屬性指定其 DSN(資料來源名稱)。不同資料庫的 DSN 格式各不相同 -

  • MySQL、MariaDB - mysql:host = localhost;dbname = mydb

  • PostgreSQL - pgsql:host = localhost;port = 5432;dbname = mydb

  • SQLite - sqlite:/path/to/db/file

  • MS SQL Server(透過 sqlsrv 驅動程式) - sqlsrv:Server = localhost;Database = mydb

  • MS SQL Server(透過 mssql 驅動程式) - mssql:host = localhost;dbname = mydb

  • MS SQL Server(透過 dblib 驅動程式) - dblib:host = localhost;dbname = mydb

  • CUBRID - cubrid:dbname = mydb;host = localhost;port = 33000

  • Oracle - oci:dbname = //:1521/mydb

為了展示資料庫查詢的實際應用,我們需要資料。

準備資料庫

步驟 1 − 建立一個新的資料庫。資料庫可以透過以下兩種方式準備。

  • 在終端執行mysql -u root –p

  • 透過CREATE DATABASE helloworld CHARACTER SET utf8 COLLATE utf8_general_ci;建立一個新的資料庫。

步驟 2 − 在config/db.php檔案中配置資料庫連線。以下配置適用於當前使用的系統。

<?php
   return [
      'class' => 'yii\db\Connection',
      'dsn' => 'mysql:host = localhost;dbname = helloworld',
      'username' => 'vladimir',
      'password' => '12345',
      'charset' => 'utf8',
   ];
?>

步驟 3 − 在根資料夾中執行 ./yii migrate/create test_table。此命令將建立一個用於管理我們資料庫的資料庫遷移。遷移檔案應該出現在專案根目錄的migrations資料夾中。

步驟 4 − 以這種方式修改遷移檔案(在本例中為m160106_163154_test_table.php)。

<?php
   use yii\db\Schema;
   use yii\db\Migration;
   class m160106_163154_test_table extends Migration {
      public function safeUp() {
         $this->createTable("user", [
            "id" => Schema::TYPE_PK,
            "name" => Schema::TYPE_STRING,
            "email" => Schema::TYPE_STRING,
         ]);
         $this->batchInsert("user", ["name", "email"], [
            ["User1", "user1@gmail.com"],
            ["User2", "user2@gmail.com"],
            ["User3", "user3@gmail.com"],
            ["User4", "user4@gmail.com"],
            ["User5", "user5@gmail.com"],
            ["User6", "user6@gmail.com"],
            ["User7", "user7@gmail.com"],
            ["User8", "user8@gmail.com"],
            ["User9", "user9@gmail.com"],
            ["User10", "user10@gmail.com"],
            ["User11", "user11@gmail.com"],
         ]);
      }
      public function safeDown() {
         $this->dropTable('user');
      }
   }
?>

以上遷移建立了一個user表,其中包含以下欄位:id、name和email。它還添加了一些演示使用者。

步驟 5 − 在專案根目錄中執行 ./yii migrate以將遷移應用於資料庫。

步驟 6 − 現在,我們需要為我們的user表建立一個模型。為簡單起見,我們將使用Gii程式碼生成工具。開啟此URL:https://:8080/index.php?r=gii。然後,單擊“模型生成器”標題下的“開始”按鈕。填寫表名(“user”)和模型類(“MyUser”),單擊“預覽”按鈕,最後單擊“生成”按鈕。

database Access Preparing DB

MyUser模型應該出現在models目錄中。

Yii - 資料訪問物件

要執行SQL 查詢,您應該按照以下步驟操作 -

  • 使用 SQL 查詢建立一個yii\db\Command
  • 繫結引數(非必需)
  • 執行命令。

步驟 1 - 在 SiteController 中建立一個名為actionTestDb的函式。

public function actionTestDb(){
   // return a set of rows. each row is an associative array of column names and values.
   // an empty array is returned if the query returned no results
   $users = Yii::$app->db->createCommand('SELECT * FROM user LIMIT 5')
      ->queryAll();
   var_dump($users);
   // return a single row (the first row)
   // false is returned if the query has no result
   $user = Yii::$app->db->createCommand('SELECT * FROM user WHERE id=1')
      ->queryOne();
   var_dump($user);
   // return a single column (the first column)
   // an empty array is returned if the query returned no results
   $userName = Yii::$app->db->createCommand('SELECT name FROM user')
      ->queryColumn();
   var_dump($userName);
   // return a scalar value
   // false is returned if the query has no result
   $count = Yii::$app->db->createCommand('SELECT COUNT(*) FROM user')
      ->queryScalar();
   var_dump($count);
}

上面的示例展示了從 DB 中獲取資料的各種方法。

步驟 2 - 訪問地址https://:8080/index.php?r=site/test-db,您將看到以下輸出。

Create actionTestDb Output

建立 SQL 命令

要使用引數建立 SQL 命令,您應該始終使用繫結引數的方法來防止 SQL 注入。

步驟 1 - 請按以下方式修改actionTestDb方法。

public function actionTestDb() {
   $firstUser = Yii::$app->db->createCommand('SELECT * FROM user WHERE id = :id')
      ->bindValue(':id', 1)
      ->queryOne();
   var_dump($firstUser);
   $params = [':id' => 2, ':name' => 'User2'];
   $secondUser = Yii::$app->db->createCommand('SELECT * FROM user WHERE
      id = :id AND name = :name')
      ->bindValues($params)
      ->queryOne();
   var_dump($secondUser);
      //another approach
   $params = [':id' => 3, ':name' => 'User3'];
   $thirdUser = Yii::$app->db->createCommand('SELECT * FROM user WHERE
      id = :id AND name = :name', $params)
      ->queryOne();
   var_dump($thirdUser);
}

在上面的程式碼中 -

  • bindValue() - 繫結單個引數值。

  • bindValues() - 繫結多個引數值。

步驟 2 - 如果您訪問地址https://:8080/index.php?r=site/test-db,您將看到以下輸出。

Modified actionTestDb Output

INSERT、UPDATE 和 DELETE 查詢

對於 INSERT、UPDATE 和 DELETE 查詢,您可以呼叫 insert()、update() 和 delete() 方法。

步驟 1 - 請按以下方式修改actionTestDb方法。

public function actionTestDb() {
   public function actionTestDb(){
      // INSERT (table name, column values)
      Yii::$app->db->createCommand()->insert('user', [
         'name' => 'My New User',
         'email' => 'mynewuser@gmail.com',
      ])->execute();
      $user = Yii::$app->db->createCommand('SELECT * FROM user WHERE name = :name')
         ->bindValue(':name', 'My New User')
         ->queryOne();
      var_dump($user);
      // UPDATE (table name, column values, condition)
      Yii::$app->db->createCommand()->update('user', ['name' => 'My New User
         Updated'], 'name = "My New User"')->execute();
      $user = Yii::$app->db->createCommand('SELECT * FROM user WHERE name = :name')
         ->bindValue(':name', 'My New User Updated')
         ->queryOne();
      var_dump($user);
      // DELETE (table name, condition)
      Yii::$app->db->createCommand()->delete('user', 'name = "My New User
         Updated"')->execute();
      $user = Yii::$app->db->createCommand('SELECT * FROM user WHERE name = :name')
         ->bindValue(':name', 'My New User Updated')
         ->queryOne();
      var_dump($user);
   }
}

步驟 2 - 在 Web 瀏覽器的位址列中鍵入 URLhttps://:8080/index.php?r=site/test-db,您將看到以下輸出。

Insert Update Delete Queries Example

Yii - 查詢構建器

查詢構建器允許您以程式設計方式建立 SQL 查詢。查詢構建器可幫助您編寫更易讀的 SQL 相關程式碼。

要使用查詢構建器,您應該按照以下步驟操作 -

  • 構建一個 yii\db\Query 物件。
  • 執行查詢方法。

要構建yii\db\Query物件,您應該呼叫不同的查詢構建器函式來定義 SQL 查詢的不同部分。

步驟 1 - 為了展示查詢構建器的典型用法,請按以下方式修改actionTestDb方法。

public function actionTestDb() {
   //generates "SELECT id, name, email FROM user WHERE name = 'User10';"
   $user = (new \yii\db\Query())
      ->select(['id', 'name', 'email'])
      ->from('user')
      ->where(['name' => 'User10'])
      ->one();
   var_dump($user);
}

步驟 2 - 訪問https://:8080/index.php?r=site/test-db,您將看到以下輸出。

Query Builder

Where() 函式

where()函式定義查詢的 WHERE 片段。要指定WHERE條件,您可以使用三種格式。

  • 字串格式 - 'name = User10'

  • 雜湊格式 - ['name' => 'User10', 'email => user10@gmail.com']

  • 運算子格式 - ['like', 'name', 'User']

字串格式示例

public function actionTestDb() {
   $user = (new \yii\db\Query())
      ->select(['id', 'name', 'email'])
      ->from('user')
      ->where('name = :name', [':name' => 'User11'])
      ->one();
   var_dump($user);
}

輸出如下。

String Format Example Output

雜湊格式示例

public function actionTestDb() {
   $user = (new \yii\db\Query())
      ->select(['id', 'name', 'email'])
      ->from('user')
      ->where([
         'name' => 'User5',
         'email' => 'user5@gmail.com'
      ])
      ->one();
   var_dump($user);
}

輸出如下。

Hash Format Example Output

運算子格式允許您以以下格式定義任意條件 -

[operator, operand1, operand2]

運算子可以是 −

  • and − ['and', 'id = 1', 'id = 2'] 將生成 id = 1 AND id = 2 或者:類似於 and 運算子

  • between − ['between', 'id', 1, 15] 將生成 id BETWEEN 1 AND 15

  • not between − 類似於 between 運算子,但 BETWEEN 被替換為 NOT BETWEEN

  • in − ['in', 'id', [5,10,15]] 將生成 id IN (5,10,15)

  • not in − 類似於 in 運算子,但 IN 被替換為 NOT IN

  • like − ['like', 'name', 'user'] 將生成 name LIKE '%user%'

  • or like − 類似於 like 運算子,但使用 OR 分隔 LIKE 謂詞

  • not like − 類似於 like 運算子,但 LIKE 被替換為 NOT LIKE

  • or not like − 類似於 not like 運算子,但使用 OR 連線 NOT LIKE 謂詞

  • exists − 需要一個運算元,該運算元必須是 yii\db\Query 類的例項

  • not exists − 類似於 exists 運算子,但構建 NOT EXISTS (子查詢) 表示式

  • <, <=, >, >=, 或任何其他資料庫運算子:['<', 'id', 10] 將生成 id<10

運算子格式示例

public function actionTestDb() {
   $users = (new \yii\db\Query())
      ->select(['id', 'name', 'email'])
      ->from('user')
      ->where(['between', 'id', 5, 7])
      ->all();
   var_dump($users);
}

輸出如下。

Operator Format Example Output

OrderBy() 函式

orderBy() 函式定義 ORDER BY 片段。

示例

public function actionTestDb() {
   $users = (new \yii\db\Query())
      ->select(['id', 'name', 'email'])
      ->from('user')
      ->orderBy('name DESC')
      ->all();
   var_dump($users);
}

輸出如下。

OrderBy Function Example Output

groupBy() 函式

groupBy() 函式定義 GROUP BY 片段,而 having() 方法指定 HAVING 片段。

示例

public function actionTestDb() {
   $users = (new \yii\db\Query())
      ->select(['id', 'name', 'email'])
      ->from('user')
      ->groupBy('name')
      ->having('id < 5')
      ->all();
   var_dump($users);
}

輸出如下。

groupBy Function Example Output

limit()offset() 方法定義 LIMITOFFSET 片段。

示例

public function actionTestDb() {
   $users = (new \yii\db\Query())
      ->select(['id', 'name', 'email'])
      ->from('user')
      ->limit(5)
      ->offset(5)
      ->all();
   var_dump($users);
}

您可以看到以下輸出 −

Limit Offset Fragments

yii\db\Query 類提供了一組用於不同目的的方法 −

  • all() − 返回一個包含名稱-值對的行陣列。

  • one() − 返回第一行。

  • column() − 返回第一列。

  • scalar() − 返回結果集第一行第一列的標量值。

  • exists() − 返回一個值,指示查詢是否包含任何結果

  • count() 返回 COUNT 查詢的結果

  • 其他聚合查詢方法 − 包括 sum($q)、average($q)、max($q)、min($q)。$q 引數可以是列名或資料庫表示式。

Yii - 活動記錄

Active Record 提供了一個面向物件的 API 用於訪問資料。一個 Active Record 類與一個數據庫表關聯。

Yii 為以下關係型資料庫提供了 Active Record 支援 −

  • MySQL 4.1 或更高版本
  • SQLite 2 和 3
  • PostgreSQL 7.3 或更高版本
  • Microsoft SQL Server 2008 或更高版本
  • CUBRID 9.3 或更高版本
  • Oracle
  • ElasticSearch
  • Sphinx

此外,Active Record 類還支援以下 NoSQL 資料庫 −

  • Redis 2.6.12 或更高版本
  • MongoDB 1.3.0 或更高版本

為單獨的資料庫表宣告一個 Active Record 類(在本例中為 MyUser 模型)後,您應該按照以下步驟從該表中查詢資料 −

  • 使用 yii\db\ActiveRecord::find() 方法建立一個新的查詢物件。
  • 構建查詢物件。
  • 呼叫查詢方法以檢索資料。

步驟 1 − 以這種方式修改 actionTestDb() 方法。

public function actionTestDb() {
   // return a single user whose ID is 1
   // SELECT * FROM `user` WHERE `id` = 1
   $user = MyUser::find()
      ->where(['id' => 1])
      ->one();
   var_dump($user);
   // return the number of users
   // SELECT COUNT(*) FROM `user`
   $users = MyUser::find()
      ->count();
   var_dump($users);
   // return all users and order them by their IDs
   // SELECT * FROM `user` ORDER BY `id`
   $users = MyUser::find()
      ->orderBy('id')
      ->all();
   var_dump($users);
}

上面給出的程式碼展示瞭如何使用 ActiveQuery 查詢資料。

步驟 2 - 訪問https://:8080/index.php?r=site/test-db,您將看到以下輸出。

Active Record

按主鍵值或一組列值進行查詢是一項常見的任務,因此 Yii 提供了以下方法 −

  • yii\db\ActiveRecord::findOne() − 返回單個 Active Record 例項

  • yi\db\ActiveRecord::findAll() − 返回一個 Active Record 例項陣列

示例

public function actionTestDb() {
   // returns a single customer whose ID is 1
   // SELECT * FROM `user` WHERE `id` = 1
   $user = MyUser::findOne(1);
   var_dump($user);
   // returns customers whose ID is 1,2,3, or 4
   // SELECT * FROM `user` WHERE `id` IN (1,2,3,4)
   $users = MyUser::findAll([1, 2, 3, 4]);
   var_dump($users);
   // returns a user whose ID is 5
   // SELECT * FROM `user` WHERE `id` = 5
   $user = MyUser::findOne([
      'id' => 5
   ]);
   var_dump($user);
}

將資料儲存到資料庫

要將資料儲存到資料庫,您應該呼叫 yii\db\ActiveRecord::save() 方法。

步驟 1 − 以這種方式修改 actionTestDb() 方法。

public function actionTestDb() {
   // insert a new row of data
   $user = new MyUser();
   $user->name = 'MyCustomUser2';
   $user->email = 'mycustomuser@gmail.com';
   $user->save();
   var_dump($user->attributes);
   
   // update an existing row of data
   $user = MyUser::findOne(['name' => 'MyCustomUser2']);
   $user->email = 'newemail@gmail.com';
   $user->save();
   var_dump($user->attributes);
}

步驟 2 - 訪問https://:8080/index.php?r=site/test-db,您將看到以下輸出。

Save Data to Database

要刪除一行資料,您應該 −

  • 檢索 Active Record 例項

  • 呼叫 yii\db\ActiveRecord::delete() 方法

步驟 1 − 以這種方式修改 actionTestDb() 方法。

public function actionTestDb() {
   $user = MyUser::findOne(2);
   if($user->delete()) {
      echo "deleted";
   } 
}

步驟 2 − 在 Web 瀏覽器的位址列中鍵入 https://:8080/index.php?r=site/test-db,您將看到以下輸出。

Delete Single Row Data

步驟 3 − 您還可以呼叫 yii\db\ActiveRecord::deleteAll() 方法刪除多行資料,例如。

public function actionTestDb() {
    MyUser::deleteAll('id >= 20');
}

Yii - 資料庫遷移

在開發資料庫驅動的應用程式期間,資料庫結構會隨著原始碼而發展。Yii 提供了 資料庫遷移功能,允許您跟蹤資料庫更改。

Yii 提供了以下遷移命令列工具 −

  • 建立新的遷移
  • 回滾遷移
  • 應用遷移
  • 重新應用遷移
  • 顯示遷移狀態和歷史記錄

建立遷移

讓我們建立一個新的資料庫遷移。

步驟 1 − 在基本應用程式模板的專案根目錄中開啟控制檯視窗並執行。

./yii migrate/create add_news_table

上述命令將在 migrations 資料夾中建立一個新的遷移檔案(在本例中為 m160113_102634_add_news_table.php)。

該檔案包含以下程式碼 −

<?php
   use yii\db\Schema;
   use yii\db\Migration;
   class m160113_102634_add_news_table extends Migration {
      public function up() {
   
      }
      public function down() {
         echo "m160113_102634_add_news_table cannot be reverted.\n";
         return false;
      }
      /*
      // Use safeUp/safeDown to run migration code within a transaction
      public function safeUp() {
 
      }
      public function safeDown() {
   
      }
      */
   }
?>

每個資料庫遷移都是一個擴充套件 yii\db\Migration 類的 PHP 類。類名按以下格式生成 −

m<YYMMDD_HHMMSS>_<Name>

其中 <YYMMDD_HMMSS> 是執行遷移命令時的 UTC 日期時間,<Name> 是您在控制檯命令中提供的引數。

當您升級資料庫時會呼叫 up() 方法,而當您降級資料庫時會呼叫 down() 方法。

步驟 2 − 要向資料庫新增新表,請按這種方式修改遷移檔案。

<?php
   use yii\db\Schema;
   use yii\db\Migration;
   class m160113_102634_add_news_table extends Migration {
      public function up() {
         $this->createTable("news", [
            "id" => Schema::TYPE_PK,
            "title" => Schema::TYPE_STRING,
            "content" => Schema::TYPE_TEXT,
         ]);
      }
      public function down() {
         $this->dropTable('news');
      }
      /*
      // Use safeUp/safeDown to run migration code within a transaction
      public function safeUp() {
	
      }
      public function safeDown() {

      }
      */
   }
?>

在上面的程式碼中,我們在 up() 方法中建立了一個名為 news 的新表,並在 down() 方法中刪除了該表。

news 表包含三個欄位:id、title 和 content。在建立表或列時,我們應該使用抽象型別,以便遷移獨立於資料庫型別。例如,在 MySQL 的情況下,TYPE_PK 將轉換為 int(11) NOT NUL AUTO_INCREMETN PRIMARY KEY。

步驟 3 − 要升級資料庫,請執行此命令。

./yii migrate

Upgrade Database

上述命令將列出所有尚未應用的可用遷移。然後,如果您確認要應用遷移,它將在所有新的遷移類中執行 safeUp() 或 up()。

步驟 4 − 要僅應用三個可用的遷移,您可以執行。

./yii migrate 3

步驟 5 − 您還可以定義資料庫應遷移到的特定遷移。

# 使用時間戳指定遷移

yii migrate/to 160202_195501

# 使用可以由 strtotime() 解析的字串

yii migrate/to "2016-01-01 19:55:01"

# 使用完整名稱

yii migrate/to m160202_195501_create_news_table

# 使用 UNIX 時間戳

yii migrate/to 1393964718

步驟 6 − 要回滾遷移(執行 down() 或 safeDown() 方法),請執行。

./yii migrate/down

Revert Migration

步驟 7 − 要回滾最近應用的五個遷移,您可以執行。

./yii migrate/down 5

步驟 8 − 要重做(回滾然後重新應用)遷移,請執行。

./yii migrate/redo

Redo Migration

要列出已應用的遷移,請使用以下命令 −

  • yii migrate/new # 顯示前 10 個新的遷移

  • yii migrate/new 3 # 顯示前 3 個新的遷移

  • yii migrate/new all # 顯示所有新的遷移

  • yii migrate/history # 顯示最後 10 個應用的遷移

  • yii migrate/history 20 # 顯示最後 20 個應用的遷移

  • yii migrate/history all # 顯示所有應用的遷移

有時您需要從特定表中新增或刪除列。您可以使用 addColumn()dropColumn() 方法。

步驟 1 − 建立一個新的遷移。

./yii migrate/create add_category_to_news

步驟 2 − 按這種方式修改新建立的遷移檔案。

<?php
   use yii\db\Schema;
   use yii\db\Migration;
   class m160113_110909_add_category_to_news extends Migration {
      public function up() {
         $this->addColumn('news', 'category', $this->integer());
      }
      public function down() {
         $this->dropColumn('news', 'category');
      }
   }
?>

現在,如果您執行 ./yii migrate,category 列應該會新增到 news 表中。相反,如果您執行 ./yii migrate/down 1,category 列應該會被刪除。

在執行資料庫遷移時,務必確保每個遷移都成功或失敗。建議將資料庫操作包含在事務中。要實現事務性遷移,您只需將遷移程式碼放在 safeUp()safeDown() 方法中即可。如果這些方法中的任何操作失敗,則所有先前操作都將回滾。

“事務方式”中的先前示例將為 −

<?php
   use yii\db\Schema;
   use yii\db\Migration;
   class m160113_110909_add_category_to_news extends Migration {
      public function safeUp() {
         $this->addColumn('news', 'category', $this->integer());
      }
      public function safeDown() {
         $this->dropColumn('news', 'category');
      }
   }
?>

yii\db\Migration 類提供以下用於操作資料庫的方法 −

  • execute() − 執行原始 SQL 語句

  • createTable() − 建立表

  • renameTable() − 重命名錶

  • insert() − 插入一行

  • batchInsert() − 插入多行

  • update() − 更新行

  • delete() − 刪除行

  • addColumn() − 新增列

  • renameColumn() − 重新命名列

  • dropColumn() − 刪除列

  • alterColumn() − 修改列

  • dropTable() − 刪除表

  • truncateTable() − 刪除表中的所有行

  • createIndex() − 建立索引

  • dropIndex() − 刪除索引

  • addPrimaryKey() − 新增主鍵

  • dropPrimaryKey() − 刪除主鍵

  • addForeignKey() − 新增外部索引鍵

  • dropForeignKey() − 刪除外部索引鍵

Yii - 主題

主題化可幫助您用另一個主題替換一組檢視,而無需修改原始檢視檔案。您應該設定檢視應用程式元件的 theme 屬性以使用主題化。

您還應該定義以下屬性 −

  • yii\base\Theme::$basePath − 定義 CSS、JS、影像等的基目錄。

  • yii\base\Theme::$baseUrl − 定義主題資源的基 URL。

  • yii\base\Theme::$pathMap − 定義替換規則。

例如,如果您在 UserController 中呼叫 $this->render('create'),則將呈現 @app/views/user/create.php 檢視檔案。但是,如果您像在以下應用程式配置中一樣啟用主題化,則將呈現檢視檔案 @app/themes/basic/user/create.php,而不是。

步驟 1 − 以這種方式修改 config/web.php 檔案。

<?php
   $params = require(__DIR__ . '/params.php');
   $config = [
      'id' => 'basic',
      'basePath' => dirname(__DIR__),
      'bootstrap' => ['log'],
      'components' => [
         'request' => [
            // !!! insert a secret key in the following (if it is empty) - this
               //is required by cookie validation
            'cookieValidationKey' => 'ymoaYrebZHa8gURuolioHGlK8fLXCKjO',
         ],
         'cache' => [
            'class' => 'yii\caching\FileCache',
         ],
         'user' => [
            'identityClass' => 'app\models\User',
            'enableAutoLogin' => true,
         ],
         'errorHandler' => [
            'errorAction' => 'site/error',
         ],
         'mailer' => [
            'class' => 'yii\swiftmailer\Mailer',
            // send all mails to a file by default. You have to set
            // 'useFileTransport' to false and configure a transport
            // for the mailer to send real emails.
            'useFileTransport' => true,
         ],
         'log' => [
            'traceLevel' => YII_DEBUG ? 3 : 0,
            'targets' => [
               [
                  'class' => 'yii\log\FileTarget',
                  'levels' => ['error', 'warning'],
               ],
            ],
         ],
         'view' => [
            'theme' => [
               'basePath' => '@app/themes/basic',
               'baseUrl' => '@web/themes/basic',
               'pathMap' => [
                  '@app/views' => '@app/themes/basic',
               ],
            ],
         ],
         'db' => require(__DIR__ . '/db.php'),
      ],
      'modules' => [
         'hello' => [
            'class' => 'app\modules\hello\Hello',
         ],
      ],
      'params' => $params,
   ];
   if (YII_ENV_DEV) {
      // configuration adjustments for 'dev' environment
      $config['bootstrap'][] = 'debug';
      $config['modules']['debug'] = [
         'class' => 'yii\debug\Module',
      ];
      $config['bootstrap'][] = 'gii';
      $config['modules']['gii'] = [
         'class' => 'yii\gii\Module',
      ];
   }
   return $config;
?>

我們添加了檢視應用程式元件。

步驟 2 − 現在建立 web/themes/basic 目錄結構和 themes/basic/site。在 themes/basic/site 資料夾中建立一個名為 about.php 的檔案,其中包含以下程式碼。

<?php
   /* @var $this yii\web\View */
   use yii\helpers\Html;
   $this->title = 'About';
   $this->params['breadcrumbs'][] = $this->title;
   $this->registerMetaTag(['name' => 'keywords', 'content' => 'yii, developing,
      views, meta, tags']);
   $this->registerMetaTag(['name' => 'description', 'content' => 'This is the
      description of this page!'], 'description');
?>

<div class = "site-about">
   <h1><?= Html::encode($this->title) ?></h1>
	
   <p style = "color: red;">
      This is the About page. You may modify the following file to customize its content:
   </p> 
</div>

步驟 3 − 現在,轉到 https://:8080/index.php?r=site/about,將呈現 themes/basic/site/about.php 檔案,而不是 views/site/about.php

Create Themes

步驟 4 − 要主題化模組,請按這種方式配置 yii\base\Theme::$pathMap 屬性。

'pathMap' => [
   '@app/views' => '@app/themes/basic',
   '@app/modules' => '@app/themes/basic/modules',
],

步驟 5 − 要主題化小部件,請按這種方式配置 yii\base\Theme::$pathMap 屬性。

'pathMap' => [
   '@app/views' => '@app/themes/basic',
   '@app/widgets' => '@app/themes/basic/widgets', // <-- !!!
],

有時您需要指定一個基本主題,該主題包含應用程式的基本外觀和風格。為了實現此目標,您可以使用主題繼承。

步驟 6 − 以這種方式修改檢視應用程式元件。

'view' => [
   'theme' => [
      'basePath' => '@app/themes/basic',
      'baseUrl' => '@web/themes/basic',
      'pathMap' => [
         '@app/views' => [
            '@app/themes/christmas',
            '@app/themes/basic',
         ],
      ]
   ],
],

在上述配置中,@app/views/site/index.php 檢視檔案將被主題化為 @app/themes/christmas/site/index.php 或 @app/themes/basic/site/index.php,具體取決於哪個檔案存在。如果兩個檔案都存在,則將使用第一個檔案。

步驟 7 − 建立 themes/christmas/site 目錄結構。

步驟 8 − 現在,在 themes/christmas/site 資料夾中,建立一個名為 about.php 的檔案,其中包含以下程式碼。

<?php
   /* @var $this yii\web\View */
   use yii\helpers\Html;
   $this->title = 'About';
   $this->params['breadcrumbs'][] = $this->title;
   $this->registerMetaTag(['name' => 'keywords', 'content' => 'yii, developing,
      views, meta, tags']);
   $this->registerMetaTag(['name' => 'description', 'content' => 'This is the
      description of this page!'], 'description');
?>

<div class = "site-about">
   <h2>Christmas theme</h2>
   <img src = "http://pngimg.com/upload/fir_tree_PNG2514.png" alt = ""/>
   <p style = "color: red;">
      This is the About page. You may modify the following file to customize its content:
   </p>
</div>

步驟 9 − 如果您轉到 https://:8080/index.php?r=site/about,您將看到使用聖誕主題更新的關於頁面。

Christmas Theme

Yii - RESTful API

Yii 提供了以下用於實現 RESTful API 的有用功能 −

  • 快速原型設計
  • 可自定義的物件序列化
  • 響應格式(預設支援 JSON 和 XML)
  • 集合資料和驗證錯誤的格式化
  • 高效路由
  • 支援 HATEOAS
  • 對 OPTIONS 和 HEAD 動詞的內建支援
  • 資料快取和 HTTP 快取
  • 身份驗證和授權
  • 速率限制

要展示 RESTful API 的實際應用,我們需要資料。

準備資料庫

步驟 1 − 建立一個新的資料庫。資料庫可以透過以下兩種方式準備。

  • 在終端執行mysql -u root –p

  • 透過CREATE DATABASE helloworld CHARACTER SET utf8 COLLATE utf8_general_ci;建立一個新的資料庫。

步驟 2 − 在config/db.php檔案中配置資料庫連線。以下配置適用於當前使用的系統。

<?php
   return [
      'class' => 'yii\db\Connection',
      'dsn' => 'mysql:host = localhost;dbname = helloworld',
      'username' => 'vladimir',
      'password' => '12345',
      'charset' => 'utf8',
   ];
?>

步驟 3 − 在根資料夾中執行 ./yii migrate/create test_table。此命令將建立一個用於管理我們資料庫的資料庫遷移。遷移檔案應該出現在專案根目錄的migrations資料夾中。

步驟 4 − 以這種方式修改遷移檔案(在本例中為m160106_163154_test_table.php)。

<?php
   use yii\db\Schema;
   
   use yii\db\Migration;
   class m160106_163154_test_table extends Migration {
      public function safeUp() {
         $this->createTable("user", [
            "id" => Schema::TYPE_PK,
            "name" => Schema::TYPE_STRING,
            "email" => Schema::TYPE_STRING,
         ]);
         $this->batchInsert("user", ["name", "email"], [
            ["User1", "user1@gmail.com"],
            ["User2", "user2@gmail.com"],
            ["User3", "user3@gmail.com"],
            ["User4", "user4@gmail.com"],
            ["User5", "user5@gmail.com"], 
            ["User6", "user6@gmail.com"],
            ["User7", "user7@gmail.com"],
            ["User8", "user8@gmail.com"],
            ["User9", "user9@gmail.com"],
            ["User10", "user10@gmail.com"],
            ["User11", "user11@gmail.com"],
         ]);
      }
      public function safeDown() {
         $this->dropTable('user');
      }
   }
?>

以上遷移建立了一個user表,其中包含以下欄位:id、name和email。它還添加了一些演示使用者。

步驟 5 − 在專案根目錄中執行 ./yii migrate以將遷移應用於資料庫。

步驟 6 − 現在,我們需要為我們的user表建立一個模型。為簡單起見,我們將使用Gii程式碼生成工具。開啟此URL:https://:8080/index.php?r=gii。然後,單擊“模型生成器”標題下的“開始”按鈕。填寫表名(“user”)和模型類(“MyUser”),單擊“預覽”按鈕,最後單擊“生成”按鈕。

Model Generator

MyUser模型應該出現在models目錄中。

安裝 Postman

在開發 RESTful 服務時,Postman 是一款方便的工具。它提供了一個用於構建請求的有用介面。

您可以在 https://chrome.google.com/webstore/detail/postman/fhbjgbiflinjbdggehcddcbncdddomop?hl=en 找到此工具。

要安裝它,請按“新增到 Chrome”按鈕。

Installing Postman

Yii - RESTful API 實戰

控制器類繼承自yii\rest\ActiveController類,該類實現了常見的 RESTful 操作。我們指定$modelClass屬性,以便控制器知道要使用哪個模型來操作資料。

步驟 1 - 在 controllers 資料夾內建立一個名為UserController.php的檔案。

<?php
   namespace app\controllers;
   use yii\rest\ActiveController;
   class UserController extends ActiveController {
      public $modelClass = 'app\models\MyUser';
   }
?>

接下來,我們需要設定 urlManager 元件,以便可以使用有意義的 HTTP 動詞和漂亮的 URL 訪問和操作使用者資料。為了讓 API 以 JSON 格式訪問資料,我們應該配置request應用程式元件的 parsers 屬性。

步驟 2 - 以這種方式修改config/web.php檔案 -

<?php
   $params = require(__DIR__ . '/params.php');
   $config = [
      'id' => 'basic',
      'basePath' => dirname(__DIR__),
      'bootstrap' => ['log'],
      'components' => [
         'request' => [
            // !!! insert a secret key in the following (if it is empty) - this is 
               //required by cookie validation
            'cookieValidationKey' => 'ymoaYrebZHa8gURuolioHGlK8fLXCKjO',
         ],
         'cache' => [
            'class' => 'yii\caching\FileCache',
         ],
         'user' => [
            'identityClass' => 'app\models\User',
            'enableAutoLogin' => true,
         ],
         'errorHandler' => [
            'errorAction' => 'site/error',
         ],
         'mailer' => [
            'class' => 'yii\swiftmailer\Mailer',
            // send all mails to a file by default. You have to set
            // 'useFileTransport' to false and configure a transport
            // for the mailer to send real emails.
            'useFileTransport' => true,
         ],
         'log' => [
            'traceLevel' => YII_DEBUG ? 3 : 0,
            'targets' => [
               [
                  'class' => 'yii\log\FileTarget',
                  'levels' => ['error', 'warning'],
               ],
            ],
         ],
         'urlManager' => [
            'enablePrettyUrl' => true,
            'enableStrictParsing' => true,
            'showScriptName' => false,
            'rules' => [
               ['class' => 'yii\rest\UrlRule', 'controller' => 'user'],
            ],
         ],
         'request' => [
            'parsers' => [
               'application/json' => 'yii\web\JsonParser',
            ]
         ],
         'db' => require(__DIR__ . '/db.php'),
      ],
      'modules' => [
         'hello' => [
            'class' => 'app\modules\hello\Hello',
         ],
      ],
      'params' => $params,
   ];
   if (YII_ENV_DEV) {
      // configuration adjustments for 'dev' environment
      $config['bootstrap'][] = 'debug';
      $config['modules']['debug'] = [
         'class' => 'yii\debug\Module',
      ];
      $config['bootstrap'][] = 'gii';
      $config['modules']['gii'] = [
         'class' => 'yii\gii\Module',
      ];
   }
   return $config;
?>

只需付出最少的努力,我們就構建了一個用於訪問使用者資料的 RESTful API。這些 API 包括 -

  • GET /users - 分頁列出所有使用者

  • HEAD /users - 顯示使用者列表的概述資訊

  • POST /users - 建立一個新使用者

  • GET /users/20 - 返回使用者 20 的詳細資訊

  • HEAD /users/20 - 顯示使用者 20 的概述資訊

  • PATCH /users/ 20 和 PUT /users/20 - 更新使用者 20

  • DELETE /users/20 - 刪除使用者 20

  • OPTIONS /users - 顯示關於端點 /users 的支援的動詞

  • OPTIONS /users/20 - 顯示關於端點 /users/ 20 的支援的動詞

注意,Yii 會自動將控制器名稱變為複數。

步驟 3 - 現在,開啟 Postman,輸入https://:8080/users,然後點選“傳送”。您將看到以下內容。

Open Postman

步驟 4 - 要建立一個新使用者,請將請求型別更改為 POST,新增兩個主體引數:name 和 email,然後點選“傳送”。

Create New User

步驟 5 - 您可以使用fields引數指定結果中應包含哪些欄位。例如,URLhttps://:8080/users?fields=id, name 僅返回idname欄位,如下面的螢幕截圖所示。

Use Fields

Yii - 欄位

透過覆蓋fields() 和 extraFields()方法,您可以定義可以在響應中放入哪些資料。這兩種方法之間的區別在於,前者定義了預設的欄位集,這些欄位集應包含在響應中,而後者定義了其他欄位,如果終端使用者透過expand查詢引數請求這些欄位,則可以將其包含在響應中。

步驟 1 - 以這種方式修改MyUser模型。

<?php
   namespace app\models;
   use app\components\UppercaseBehavior;
   use Yii;
   /**
   * This is the model class for table "user".
   *@property integer $id
   * @property string $name
   * @property string $email
   */
   class MyUser extends \yii\db\ActiveRecord {
      public function fields() {
         return [
            'id',
            'name',
            //PHP callback
            'datetime' => function($model) {
               return date("d:m:Y H:i:s");
            }
         ];
      }
      /**
      * @inheritdoc
      */
      public static function tableName() {
         return 'user';
      }
      /**
      * @inheritdoc
      */
      public function rules() {
         return [
            [['name', 'email'], 'string', 'max' => 255]
         ];
      }
      /**
      * @inheritdoc
      */
      public function attributeLabels() {
         return [
            'id' => 'ID',
            'name' => 'Name',
            'email' => 'Email',
         ];
      }
   }
?>

除了預設欄位:id 和 name 之外,我們還添加了一個自定義欄位 - datetime

步驟 2 - 在 Postman 中,執行 URLhttps://:8080/users

Run URL

步驟 3 - 現在,以這種方式修改MyUser模型。

<?php
   namespace app\models;
   use app\components\UppercaseBehavior;
   use Yii;
   /**
   * This is the model class for table "user".
   *
   * @property integer $id
   * @property string $name
   * @property string $email
   */
   class MyUser extends \yii\db\ActiveRecord {
      public function fields() {
         return [
            'id',
            'name',
         ];
      }
      public function extraFields() {
         return ['email'];
      }
      /**
      * @inheritdoc
      */
      public static function tableName() {
         return 'user';
      }
      /**
      * @inheritdoc
      */
      public function rules() { 
         return [
            [['name', 'email'], 'string', 'max' => 255]
         ];
      }
      /**
      * @inheritdoc
      */
      public function attributeLabels() { 
         return [
            'id' => 'ID',
            'name' => 'Name',
            'email' => 'Email',
         ];
      }
   } 
?>

注意,email 欄位由extraFields()方法返回。

步驟 4 - 要獲取包含此欄位的資料,請執行https://:8080/users?expand=email

Get Data

自定義操作

yii\rest\ActiveController類提供以下操作 -

  • Index - 分頁列出資源

  • View - 返回指定資源的詳細資訊

  • Create - 建立一個新資源

  • Update - 更新現有資源

  • Delete - 刪除指定的資源

  • Options - 返回支援的 HTTP 方法

所有上述操作都在 actions 方法() 中宣告。

要停用“delete”和“create”操作,請以這種方式修改UserController -

<?php
   namespace app\controllers;
   use yii\rest\ActiveController;
   class UserController extends ActiveController {
      public $modelClass = 'app\models\MyUser';
      public function actions() {
         $actions = parent::actions();
         // disable the "delete" and "create" actions
         unset($actions['delete'], $actions['create']);
         return $actions;
      }
   }
?>

處理錯誤

在獲取 RESTful API 請求時,如果請求中存在錯誤或伺服器上發生意外情況,您可以簡單地丟擲一個異常。如果您可以識別錯誤的原因,則應丟擲一個異常以及適當的 HTTP 狀態程式碼。Yii REST 使用以下狀態 -

  • 200 - OK。

  • 201 - 響應 POST 請求成功建立了一個資源。Location 標頭包含指向新建立資源的 URL。

  • 204 - 請求已成功處理,並且響應不包含內容。

  • 304 - 資源未修改。

  • 400 - 錯誤請求。

  • 401 - 身份驗證失敗。

  • 403 - 已認證的使用者無權訪問指定的 API 端點。

  • 404 - 資源不存在。

  • 405 - 方法不允許。

  • 415 - 不支援的媒體型別。

  • 422 - 資料驗證失敗。

  • 429 - 請求過多。

  • 500 - 內部伺服器錯誤。

Yii - 測試

當我們編寫 PHP 類時,我們會逐步除錯它或使用 die 或 echo 語句來驗證它的工作方式。如果我們開發一個 Web 應用程式,我們會將測試資料輸入表單中以確保頁面按預期工作。此測試過程可以自動化。

自動測試方法對於長期專案很有意義,這些專案 -

  • 複雜且龐大
  • 不斷發展
  • 在失敗成本方面過於昂貴

如果您的專案沒有變得複雜,並且相對簡單,或者它只是一個一次性專案,那麼自動化測試可能有點過頭了。

準備測試

步驟 1 - 安裝 Codeception 框架。執行以下程式碼。

composer global require "codeception/codeception = 2.0.*"
composer global require "codeception/specify = *"
composer global require "codeception/verify = *"

步驟 2 - 執行以下命令。

composer global status

輸出為“Changed current directory to <directory>”。您應該將'<directory>/vendor/bin'新增到您的 PATH 變數中。在這種情況下,執行以下程式碼 -

export PATH = $PATH:~/.composer/vendor/bin

步驟 3 - 建立一個名為'yii2_basic_tests'的新資料庫。

步驟 4 - 在 tests 目錄中執行。

codeception/bin/yii migrate

資料庫配置可以在tests/codeception/config/config.php中找到。

步驟 5 - 透過以下命令構建測試套件。

codecept build

Fixture

Fixture 的主要目的是在未知狀態下設定環境,以便您的測試以預期的方式執行。Yii 提供了一個近似 Fixture 框架。Yii Fixture 框架的一個關鍵概念是 Fixture 物件。它表示測試環境的特定方面。Fixture 物件是yii\test\Fixture 類的例項。

要定義一個 Fixture,您應該建立一個新類並將其擴充套件自 yii\test\Fixture 或 yii\test\ActiveFixture。前者更適合通用 Fixture,而後者專門設計用於與資料庫和 ActiveRecord 一起使用。

單元測試

單元測試可以幫助您測試單個函式。例如,模型函式或元件類。

步驟 1 - 在tests/codeception/fixtures目錄下的名為ExampleFixture.php的檔案中建立一個新的 Fixture。

<?php
   namespace app\tests\codeception\fixtures;
   use yii\test\ActiveFixture;
   class ExampleFixture extends ActiveFixture {
      public $modelClass = ‘app⊨’MyUser';
   }
?>

步驟 2 - 然後,在 tests/codeception/unit/models 資料夾中建立一個名為 ExampleTest.php 的新測試檔案。

<?php
   namespace tests\codeception\unit\models;
   use app\models\MyUser;
   use yii\codeception\TestCase;
   class ExampleTest extends TestCase {
      public function testCreateMyUser() {
         $m = new MyUser();
         $m->name = "myuser";
         $m->email = "myser@email.com";
         $this->assertTrue($m->save());
      }
      public function testUpdateMyUser() {
         $m = new MyUser();
         $m->name = "myuser2";
         $m->email = "myser2@email.com";
         $this->assertTrue($m->save());
         $this->assertEquals("myuser2", $m->name);
      }
      public function testDeleteMyUser() {
         $m = MyUser::findOne(['name' => 'myuser2']);
         $this->assertNotNull($m);
         MyUser::deleteAll(['name' => $m->name]);
         $m = MyUser::findOne(['name' => 'myuser2']);
         $this->assertNull($m);
      }
   }
?>

在上面的程式碼中,我們定義了三個測試 -

  • testCreateMyUser,
  • testUpdateMyUser 和
  • testDeleteMyUser。

我們剛剛建立了一個新使用者,更新了他的姓名,並嘗試刪除他。我們根據 yii2_basic_tests 資料庫管理 MyUser 模型,它是我們真實資料庫的完整副本。

步驟 3 - 要啟動測試,請移動到 tests 資料夾並執行。

codecept run unit models/ExampleTest

它應該透過所有測試。您將看到以下內容 -

Unit Tests

功能測試

功能測試可以幫助您 -

  • 使用瀏覽器模擬器測試應用程式
  • 驗證函式是否正常工作
  • 與資料庫互動
  • 將資料提交到伺服器端指令碼

在 tests 資料夾中執行 -

generate:cept functional AboutPageCept

以上命令在 tests/codeception/functional 資料夾下建立AboutPageCept.php檔案。在這個功能測試中,我們將檢查我們的about頁面是否存在。

步驟 1 - 修改AboutPageCept.php檔案。

<?php
   $I = new FunctionalTester($scenario);
   $I->wantTo('perform actions and see result');
   $I->amOnPage('site/about');
   $I->see('about');
   $I->dontSee('apple');
?>

在上面給出的程式碼中,我們檢查了我們是否在 about 頁面上。顯然,我們應該在頁面上看到“about”這個詞,而沒有“apple”。

步驟 2 - 透過以下命令執行測試。

run functional AboutPageCept

您將看到以下輸出 -

Run Unit Tests

Yii - 快取

快取是提高應用程式效能的有效方法。快取機制將靜態資料儲存在快取中,並在請求時從快取中獲取。在伺服器端,您可以使用快取來儲存基本資料,例如最近新聞列表。您還可以儲存頁面片段或整個網頁。在客戶端,您可以使用 HTTP 快取將最近訪問的頁面儲存在瀏覽器快取中。

準備資料庫

步驟 1 − 建立一個新的資料庫。資料庫可以透過以下兩種方式準備。

  • 在終端執行mysql -u root –p

    .
  • 透過CREATE DATABASE helloworld CHARACTER SET utf8 COLLATE utf8_general_ci;建立一個新的資料庫。

步驟 2 − 在config/db.php檔案中配置資料庫連線。以下配置適用於當前使用的系統。

<?php
   return [
      'class' => 'yii\db\Connection',
      'dsn' => 'mysql:host=localhost;dbname=helloworld',
      'username' => 'vladimir',
      'password' => '12345',
      'charset' => 'utf8',
   ];
?>

步驟 3 − 在根資料夾中執行 ./yii migrate/create test_table。此命令將建立一個用於管理我們資料庫的資料庫遷移。遷移檔案應該出現在專案根目錄的migrations資料夾中。

步驟 4 − 以這種方式修改遷移檔案(在本例中為m160106_163154_test_table.php)。

<?php
   use yii\db\Schema;
   use yii\db\Migration;
   class m160106_163154_test_table extends Migration {
      public function safeUp()\ {
         $this->createTable("user", [
            "id" => Schema::TYPE_PK,
            "name" => Schema::TYPE_STRING,
            "email" => Schema::TYPE_STRING,
         ]);
         $this->batchInsert("user", ["name", "email"], [
            ["User1", "user1@gmail.com"],
            ["User2", "user2@gmail.com"],
            ["User3", "user3@gmail.com"],
            ["User4", "user4@gmail.com"],
            ["User5", "user5@gmail.com"],
            ["User6", "user6@gmail.com"],
            ["User7", "user7@gmail.com"],
            ["User8", "user8@gmail.com"],
            ["User9", "user9@gmail.com"],
            ["User10", "user10@gmail.com"],
            ["User11", "user11@gmail.com"],
         ]);
      }
      public function safeDown() {
         $this->dropTable('user');
      }
   }
?>

以上遷移建立了一個user表,其中包含以下欄位:id、name和email。它還添加了一些演示使用者。

步驟 5 − 在專案根目錄中執行 ./yii migrate以將遷移應用於資料庫。

步驟 6 − 現在,我們需要為我們的user表建立一個模型。為簡單起見,我們將使用Gii程式碼生成工具。開啟此URL:https://:8080/index.php?r=gii。然後,單擊“模型生成器”標題下的“開始”按鈕。填寫表名(“user”)和模型類(“MyUser”),單擊“預覽”按鈕,最後單擊“生成”按鈕。

Caching Preparing DB

MyUser模型應該出現在models目錄中。

資料快取

資料快取可以幫助您將 PHP 變數儲存在快取中並在以後檢索它們。資料快取依賴於快取元件,這些元件通常註冊為應用程式元件。要訪問應用程式元件,您可以呼叫Yii::$app → cache。您可以註冊多個快取應用程式元件。

Yii 支援以下快取儲存 -

  • yii\caching\DbCache - 使用資料庫表儲存快取資料。您必須建立一個表,如 yii\caching\DbCache::$cacheTable 中所指定。

  • yii\caching\ApcCache - 使用 PHP APC 擴充套件。

  • yii\caching\FileCache - 使用檔案儲存快取資料。

  • yii\caching\DummyCache - 充當快取佔位符,不執行任何實際快取。此元件的目的是簡化需要檢查快取可用性的程式碼。

  • yii\caching\MemCache - 使用 PHP memcache 擴充套件。

  • yii\caching\WinCache - 使用 PHP WinCache 擴充套件。

  • yii\redis\Cache - 實現一個基於 Redis 資料庫的快取元件。

  • yii\caching\XCache - 使用 PHP XCache 擴充套件。

所有快取元件都支援以下 API -

  • get() - 使用指定的鍵從快取中檢索資料值。如果資料值已過期/失效或未找到,則將返回 false 值。

  • add() - 如果快取中未找到鍵,則將由鍵標識的資料值儲存在快取中。

  • set() - 將由鍵標識的資料值儲存在快取中。

  • multiGet() - 使用指定的鍵從快取中檢索多個數據值。

  • multiAdd() - 將多個數據值儲存在快取中。每個專案都由一個鍵標識。如果快取中已存在鍵,則將跳過資料值。

  • multiSet() - 將多個數據值儲存在快取中。每個專案都由一個鍵標識。

  • exists() - 返回一個值,指示快取中是否找到了指定的鍵。

  • flush() - 從快取中刪除所有資料值。

  • delete() - 從快取中刪除由鍵標識的資料值。

儲存在快取中的資料值將永遠保留在那裡,除非將其刪除。要更改此行為,您可以在呼叫 set() 方法儲存資料值時設定過期引數。

快取的資料值也可以透過快取依賴項的變化來失效 -

  • yii\caching\DbDependency - 如果指定 SQL 語句的查詢結果發生更改,則依賴項將發生更改。

  • yii\caching\ChainedDependency - 如果鏈上的任何依賴項發生更改,則依賴項將發生更改。

  • yii\caching\FileDependency - 如果檔案的最後修改時間發生變化,則依賴項也會發生變化。

  • yii\caching\ExpressionDependency - 如果指定 PHP 表示式的結果發生變化,則依賴項也會發生變化。

現在,將cache應用程式元件新增到您的應用程式中。

步驟 1 - 修改config/web.php檔案。

<?php
   $params = require(__DIR__ . '/params.php');
   $config = [
      'id' => 'basic',
      'basePath' => dirname(__DIR__),
      'bootstrap' => ['log'],
      'components' => [
         'request' => [
            // !!! insert a secret key in the following (if it is empty) - this
               //is required by cookie validation
            'cookieValidationKey' => 'ymoaYrebZHa8gURuolioHGlK8fLXCKjO',
         ],
         'cache' => [
            'class' => 'yii\caching\FileCache',
         ],
         'user' => [
            'identityClass' => 'app\models\User',
            'enableAutoLogin' => true,
         ],
         'errorHandler' => [
            'errorAction' => 'site/error',
         ],
         'mailer' => [
            'class' => 'yii\swiftmailer\Mailer',
            // send all mails to a file by default. You have to set
            // 'useFileTransport' to false and configure a transport
            // for the mailer to send real emails.
            'useFileTransport' => true,
         ],
         'log' => [
            'traceLevel' => YII_DEBUG ? 3 : 0,
            'targets' => [
               [
                  'class' => 'yii\log\FileTarget',
                  'levels' => ['error', 'warning'],
               ],
            ],
         ],
         'db' => require(__DIR__ . '/db.php'),
      ],
      'modules' => [
         'hello' => [
            'class' => 'app\modules\hello\Hello',
         ],
      ],
      'params' => $params,
   ];
   if (YII_ENV_DEV) {
      // configuration adjustments for 'dev' environment
      $config['bootstrap'][] = 'debug';
      $config['modules']['debug'] = [
         'class' => 'yii\debug\Module',
      ];
      $config['bootstrap'][] = 'gii';
      $config['modules']['gii'] = [
         'class' => 'yii\gii\Module',
      ];
   }
   return $config;
?>

步驟 2 - 在 SiteController 中新增一個名為actionTestCache()的新函式。

public function actionTestCache() {
   $cache = Yii::$app->cache;
   // try retrieving $data from cache
   $data = $cache->get("my_cached_data");
   if ($data === false) {
      // $data is not found in cache, calculate it from scratch
      $data = date("d.m.Y H:i:s");
      // store $data in cache so that it can be retrieved next time
      $cache->set("my_cached_data", $data, 30);
   }
   // $data is available here
   var_dump($data);
}

步驟 3 - 在 Web 瀏覽器的位址列中鍵入https://:8080/index.php?r=site/test-cache,您將看到以下內容。

Test Cache

步驟 4 - 如果您重新載入頁面,您應該會注意到日期沒有更改。日期值被快取,快取將在 30 秒內過期。30 秒後重新載入頁面。

Date Value Cached

查詢快取

查詢快取為您提供了快取資料庫查詢結果的功能。查詢快取需要一個 DB 連線和 cache 應用程式元件。

步驟 1 - 在 SiteController 中新增一個名為actionQueryCaching()的新方法。

public function actionQueryCaching() {
   $duration = 10;
   $result = MyUser::getDb()->cache(function ($db) {
      return MyUser::find()->count();
   }, $duration);
   var_dump($result);
   $user = new MyUser();
   $user->name = "cached user name";
   $user->email = "cacheduseremail@gmail.com";
   $user->save();
   echo "==========";
   var_dump(MyUser::find()->count());
}

在上面的程式碼中,我們快取了資料庫查詢,添加了一個新使用者,並顯示了使用者數量。

步驟 2 - 訪問 URLhttps://:8080/index.php?r=site/query-caching並重新載入頁面。

Query Caching

當我們第一次開啟頁面時,我們會快取 DB 查詢並顯示所有使用者的數量。當我們重新載入頁面時,快取的 DB 查詢的結果與之前相同,因為資料庫查詢被快取了。

您可以使用以下命令從控制檯重新整理快取 -

  • yii cache - 顯示可用的快取元件。

  • yii cache/flush cache1 cache2 cache3 - 重新整理快取元件 cache1、cache2 和 cache3。

  • yii cache/flush-all - 重新整理所有快取元件。

步驟 3 - 在應用程式的專案根目錄下執行./yii cache/flush-all

Running Project Root Application

Yii - 片段快取

片段快取提供網頁片段的快取功能。

步驟 1 - 在 SiteController 中新增一個名為actionFragmentCaching()的新函式。

public function actionFragmentCaching() {
   $user = new MyUser();
   $user->name = "cached user name";
   $user->email = "cacheduseremail@gmail.com";
   $user->save();
   $models = MyUser::find()->all();
   return $this->render('cachedview', ['models' => $models]);
}

在上面的程式碼中,我們建立了一個新使用者並顯示了一個cachedview檢視檔案。

步驟 2 - 現在,在views/site資料夾中建立一個名為cachedview.php的新檔案。

<?php if ($this->beginCache('cachedview')) { ?>
   <?php foreach ($models as $model): ?>
      <?= $model->id; ?>
      <?= $model->name; ?>
      <?= $model->email; ?>
      <br/>
   <?php endforeach; ?>
<?php $this->endCache(); } ?>
<?php echo "Count:", \app\models\MyUser::find()->count(); ?>

我們將內容生成邏輯包含在一對 beginCache() 和 endCache() 方法中。如果快取中找到了內容,beginCache() 方法將呈現它。

步驟 3 - 訪問 URLhttps://:8080/index.php?r=site/fragment-caching並重新載入頁面。輸出如下。

Fragment Caching

請注意,beginCache() 和 endCache() 方法之間的內容被快取了。在資料庫中,我們有 13 個使用者,但只顯示了 12 個。

頁面快取

頁面快取提供整個網頁內容的快取功能。頁面快取由yii\filter\PageCache支援。

步驟 1 - 修改 SiteController 的behaviors()函式。

public function behaviors() {
   return [
      'access' => [
         'class' => AccessControl::className(),
         'only' => ['logout'],
         'rules' => [
            [
               'actions' => ['logout'],
               'allow' => true,
               'roles' => ['@'],
            ],
         ],
      ],
      'verbs' => [
         'class' => VerbFilter::className(),
         'actions' => [
            'logout' => ['post'],
         ],
      ],
      [
         'class' => 'yii\filters\PageCache',
         'only' => ['index'],
         'duration' => 60
      ],
   ];
}

上面的程式碼將索引頁面快取 60 秒。

步驟 2 - 訪問 URLhttps://:8080/index.php?r=site/index。然後,修改索引檢視檔案的祝賀訊息。如果重新載入頁面,您將不會注意到任何更改,因為頁面被快取了。等待一分鐘,然後再次重新載入頁面。

Page Caching

HTTP 快取

Web 應用程式還可以使用客戶端快取。要使用它,您可以為控制器操作配置yii\filter\HttpCache過濾器。

Last-Modified 標頭使用時間戳來指示頁面是否已修改。

步驟 1 - 要啟用傳送 Last-Modified 標頭,請配置 yii\filter\HttpCache::$lastModified 屬性。

public function behaviors() {
   return [
      [
         'class' => 'yii\filters\HttpCache',
         'only' => ['index'],
         'lastModified' => function ($action, $params) {
            $q = new \yii\db\Query();
            return $q->from('news')->max('created_at');
         },
      ],
   ];
}

在上面的程式碼中,我們僅為索引頁面啟用了 HTTP 快取。當瀏覽器第一次開啟索引頁面時,頁面將在伺服器端生成併發送到瀏覽器。第二次,如果沒有建立新聞,伺服器將不會重新生成頁面。

Etag 標頭提供一個表示頁面內容的雜湊值。如果頁面發生更改,雜湊值也會發生更改。

步驟 2 - 要啟用傳送 Etag 標頭,請配置yii\filters\HttpCache::$etagSeed屬性。

public function behaviors() {
   return [
      [
         'class' => 'yii\filters\HttpCache',
         'only' => ['index'],
         'etagSeed' => function ($action, $params) {
            $user = $this->findModel(\Yii::$app->request->get('id'));
            return serialize([$user->name, $user->email]);
         },
      ],
   ];
}

在上面的程式碼中,我們僅為index操作啟用了 HTTP 快取。它應該根據使用者的姓名和電子郵件生成 Etag HTTP 標頭。當瀏覽器第一次開啟索引頁面時,頁面將在伺服器端生成併發送到瀏覽器。第二次,如果姓名或電子郵件沒有更改,伺服器將不會重新生成頁面。

Yii - 別名

別名可以幫助您避免在專案中硬編碼絕對路徑或 URL。別名以 @ 字元開頭。

要定義別名,您應該呼叫Yii::setAlias()方法 -

// an alias of a file path
Yii::setAlias('@alias', '/path/to/alias');
// an alias of a URL
Yii::setAlias('@urlAlias', 'http://www.google.com');

您還可以從現有別名派生一個新別名 -

Yii::setAlias('@pathToSomewhere', '@alias/path/to/somewhere');

您可以在入口指令碼或應用程式配置中名為 aliases 的可寫屬性中呼叫 Yii::setAlias() 方法 -

$config = [
   'id' => 'basic',
   'basePath' => dirname(__DIR__),
   'bootstrap' => ['log'],
   'components' => [
      'aliases' => [
         '@alias' => '/path/to/somewhere',
         '@urlAlias' => 'http://www.google.com',
      ],
      //other components...
   ]
]

要解析別名,您應該呼叫 Yii::getAlias() 方法。

Yii 預定義了以下別名 -

  • @app - 應用程式的基本路徑。

  • @yii - BaseYii.php 檔案所在的資料夾。

  • @webroot - 應用程式的 Web 根目錄。

  • @web - 應用程式的基本 URL。

  • @runtime - 應用程式的執行時路徑。預設為 @app/runtime。

  • @vendor - Composer 供應商目錄。預設為 @app/vendor。

  • @npm - npm 包的根目錄。預設為 @vendor/npm。

  • @bower - bower 包的根目錄。預設為 @vendor/bower。

現在,在 SiteController 中新增一個名為actionAliases()的新函式 -

public function actionAliases() {
   Yii::setAlias("@components", "@app/components");
   Yii::setAlias("@imagesUrl", "@web/images");
   var_dump(Yii::getAlias("@components"));
   var_dump(Yii::getAlias("@imagesUrl"));
}

在上面的程式碼中,我們建立了兩個別名:@components 用於應用程式元件,@imagesUrl 用於儲存所有應用程式影像的 URL。

鍵入 https://:8080/index.php?r=site/aliases,您將看到以下輸出 -

Set Aliases

Yii - 日誌記錄

Yii 提供了一個高度可定製和可擴充套件的框架。藉助此框架,您可以輕鬆記錄各種型別的訊息。

要記錄訊息,您應該呼叫以下方法之一 -

  • Yii::error() - 記錄致命錯誤訊息。

  • Yii::warning() - 記錄警告訊息。

  • Yii::info() - 記錄包含一些有用資訊的訊息。

  • Yii::trace() - 記錄訊息以跟蹤程式碼片段的執行方式。

以上方法在不同的類別中記錄日誌訊息。它們共享以下函式簽名 -

function ($message, $category = 'application')

其中:

  • $message - 要記錄的日誌訊息

  • $category - 日誌訊息的類別

一種簡單方便的命名方案是使用 PHP __METHOD__ 魔術常量。例如 -

Yii::info('this is a log message', __METHOD__);

日誌目標是 yii\log\Target 類的例項。它按類別過濾所有日誌訊息,並將它們匯出到檔案、資料庫和/或電子郵件中。

步驟 1 - 您也可以註冊多個日誌目標,例如。

return [
   // the "log" component is loaded during bootstrapping time
   'bootstrap' => ['log'],
   'components' => [
      'log' => [
         'targets' => [
            [
               'class' => 'yii\log\DbTarget',
               'levels' => ['error', 'warning', 'trace', 'info'],
            ],
            [
               'class' => 'yii\log\EmailTarget',
               'levels' => ['error', 'warning'],
               'categories' => ['yii\db\*'],
               'message' => [
                  'from' => ['log@mydomain.com'],
                  'to' => ['admin@mydomain.com', 'developer@mydomain.com'],
                  'subject' => 'Application errors at mydomain.com',
               ],
            ],
         ],
      ],
   ],
];

在上面的程式碼中,註冊了兩個目標。第一個目標選擇所有錯誤、警告、跟蹤和資訊訊息,並將它們儲存在資料庫中。第二個目標將所有錯誤和警告訊息傳送到管理員電子郵件。

Yii 提供了以下內建日誌目標 -

  • yii\log\DbTarget - 將日誌訊息儲存在資料庫中。

  • yii\log\FileTarget - 將日誌訊息儲存在檔案中。

  • yii\log\EmailTarget - 將日誌訊息傳送到預定義的電子郵件地址。

  • yii\log\SyslogTarget - 透過呼叫 PHP 函式 syslog() 將日誌訊息儲存到 syslog 中。

預設情況下,日誌訊息格式如下 -

Timestamp [IP address][User ID][Session ID][Severity Level][Category] Message Text

步驟 2 - 要自定義此格式,您應該配置yii\log\Target::$prefix屬性。例如。

[
   'class' => 'yii\log\FileTarget',
   'prefix' => function ($message) {
      $user = Yii::$app->has('user', true) ? Yii::$app->get('user') :
      'undefined user';
      $userID = $user ? $user->getId(false) : 'anonym';
      return "[$userID]";
   }
]

上面的程式碼片段配置了一個日誌目標,以便在所有日誌訊息前添加當前使用者 ID。

預設情況下,日誌訊息包含以下全域性 PHP 變數的值:$_GET、$_POST、$_SESSION、$_COOKIE、$_FILES 和 $_SERVER。要修改此行為,您應該使用要包含的變數的名稱配置yii\log\Target::$logVars屬性。

所有日誌訊息都由日誌記錄器物件儲存在陣列中。日誌記錄器物件每次陣列累積一定數量的訊息(預設為 1000)時,就會將記錄的訊息重新整理到日誌目標。

步驟 3 - 要自定義此數字,您應該呼叫flushInterval 屬性

return [
   'bootstrap' => ['log'],
   'components' => [
      'log' => [
         'flushInterval' => 50, // default is 1000
         'targets' => [...],
      ],
   ],
];

即使日誌記錄器物件將日誌訊息重新整理到日誌目標,它們也不會立即匯出。匯出發生在日誌目標累積一定數量的訊息(預設為 1000)時。

步驟 4 - 要自定義此數字,您應該配置exportInterval屬性。

[
   'class' => 'yii\log\FileTarget',
   'exportInterval' => 50, // default is 1000
]

步驟 5 - 現在,以這種方式修改config/web.php檔案。

<?php
   $params = require(__DIR__ . '/params.php');
   $config = [
      'id' => 'basic',
      'basePath' => dirname(__DIR__),
      'bootstrap' => ['log'],
      'components' => [
         'request' => [
            // !!! insert a secret key in the following (if it is empty) - this
               //is required by cookie validation
            'cookieValidationKey' => 'ymoaYrebZHa8gURuolioHGlK8fLXCKjO',
         ],
         'cache' => [
            'class' => 'yii\caching\FileCache',
         ],
         'user' => [
            'identityClass' => 'app\models\User',
            'enableAutoLogin' => true,
         ],
         'errorHandler' => [
            'errorAction' => 'site/error',
         ],
         'mailer' => [
            'class' => 'yii\swiftmailer\Mailer',
            // send all mails to a file by default. You have to set
            // 'useFileTransport' to false and configure a transport
            // for the mailer to send real emails.
            'useFileTransport' => true,
         ],
         'log' => [
            'flushInterval' => 1,
            'traceLevel' => YII_DEBUG ? 3 : 0,
            'targets' => [
               [
                  'class' => 'yii\log\FileTarget',
                  'exportInterval' => 1,
                  'logVars' => []
               ],
            ],
         ],
         'db' => require(__DIR__ . '/db.php'),
      ],
      'modules' => [
         'hello' => [
            'class' => 'app\modules\hello\Hello',
         ],
      ],
      'params' => $params,
   ];
   if (YII_ENV_DEV) {
      // configuration adjustments for 'dev' environment
      $config['bootstrap'][] = 'debug';
      $config['modules']['debug'] = [
         'class' => 'yii\debug\Module',
      ];
      $config['bootstrap'][] = 'gii';
      $config['modules']['gii'] = [
         'class' => 'yii\gii\Module',
      ];
   }
   return $config;
?>

在上面的程式碼中,我們定義了 log 應用程式元件,將flushIntervalexportInteval屬性設定為 1,以便所有日誌訊息立即出現在日誌檔案中。我們還省略了日誌目標的 levels 屬性。這意味著所有類別的日誌訊息(錯誤、警告、資訊、跟蹤)都將出現在日誌檔案中。

步驟 6 - 然後,在 SiteController 中建立一個名為 actionLog() 的函式。

public function actionLog() {
   Yii::trace('trace log message');
   Yii::info('info log message');
   Yii::warning('warning log message');
   Yii::error('error log message');
}

在上面的程式碼中,我們只是將四條不同類別的日誌訊息寫入日誌檔案。

步驟 7 - 在 Web 瀏覽器的位址列中鍵入 URLhttps://:8080/index.php?r=site/log。日誌訊息應出現在 app/runtime/logs 目錄下的 app.log 檔案中。

Action Log Function

Yii - 錯誤處理

Yii 包含一個內建的錯誤處理程式。Yii 錯誤處理程式執行以下操作 -

  • 將所有非致命 PHP 錯誤轉換為可捕獲的異常。
  • 顯示所有錯誤和異常以及詳細的呼叫堆疊。
  • 支援不同的錯誤格式。
  • 支援使用控制器操作顯示錯誤。

要停用錯誤處理程式,您應該在入口指令碼中將 YII_ENABLE_ERROR_HANDLER 常量定義為 false。錯誤處理程式註冊為應用程式元件。

步驟 1 - 您可以按以下方式配置它。

return [
   'components' => [
      'errorHandler' => [
         'maxSourceLines' => 10,
      ],
   ],
];

上述配置將要顯示的原始碼行數設定為 10。錯誤處理程式將所有非致命 PHP 錯誤轉換為可捕獲的異常。

步驟 2 - 在 SiteController 中新增一個名為actionShowError()的新函式。

public function actionShowError() {
   try {
      5/0;
   } catch (ErrorException $e) {
      Yii::warning("Ooops...division by zero.");
   }
   // execution continues...
}

步驟 3 - 訪問 URLhttps://:8080/index.php?r=site/show-error。您將看到一條警告訊息。

Add actionShowError Method

如果要向用戶顯示其請求無效,可以丟擲yii\web\NotFoundHttpException異常。

步驟 4 − 修改actionShowError()函式。

public function actionShowError() {
   throw new NotFoundHttpException("Something unexpected happened");
}

步驟 5 − 在位址列中輸入地址https://:8080/index.php?r=site/show-error。您將看到以下 HTTP 錯誤。

Modify actionShowError Method

當 YII_DEBUG 常量為 true 時,錯誤處理程式將顯示帶有詳細呼叫堆疊的錯誤。當常量為 false 時,只會顯示錯誤訊息。預設情況下,錯誤處理程式使用以下檢視顯示錯誤:

  • @yii/views/errorHandler/exception.php − 當應顯示帶有呼叫堆疊資訊的錯誤時,使用此檢視檔案。

  • @yii/views/errorHandler/error.php − 當應顯示不帶呼叫堆疊資訊的錯誤時,使用此檢視檔案。

您可以使用專用的錯誤操作來自定義錯誤顯示。

步驟 6 − 修改config/web.php檔案中的errorHandler應用元件。

<?php
   $params = require(__DIR__ . '/params.php');
   $config = [
      'id' => 'basic',
      'basePath' => dirname(__DIR__),
      'bootstrap' => ['log'],
      'components' => [
         'request' => [
            // !!! insert a secret key in the following (if it is empty) - this
               //is required by cookie validation
            'cookieValidationKey' => 'ymoaYrebZHa8gURuolioHGlK8fLXCKjO',
         ],
         'cache' => [
            'class' => 'yii\caching\FileCache',
         ],
         'user' => [
            'identityClass' => 'app\models\User',
            'enableAutoLogin' => true,
         ],
         'errorHandler' => [
            'errorAction' => 'site/error',
         ],
         //other components...
            'db' => require(__DIR__ . '/db.php'),
      ],
      'modules' => [
         'hello' => [
            'class' => 'app\modules\hello\Hello',
         ],
      ],
      'params' => $params,
   ];
   if (YII_ENV_DEV) {
      // configuration adjustments for 'dev' environment
      $config['bootstrap'][] = 'debug';
      $config['modules']['debug'] = [
         'class' => 'yii\debug\Module',
      ];
      $config['bootstrap'][] = 'gii';
      $config['modules']['gii'] = [
         'class' => 'yii\gii\Module',
      ];
   }
   return $config;
?>

上述配置定義了當需要顯示不帶呼叫堆疊的錯誤時,將執行site/error操作。

步驟 7 − 修改 SiteController 的actions()方法。

public function actions() {
   return [
      'error' => [
         'class' => 'yii\web\ErrorAction',
      ],
   ];
}

以上程式碼定義了,當發生error時,將渲染錯誤檢視。

步驟 8 − 在 views/site 目錄下建立一個名為error.php的檔案。

<?php
   /* @var $this yii\web\View */
   /* @var $name string */
   /* @var $message string */
   /* @var $exception Exception */
   use yii\helpers\Html;
   $this->title = $name;
?>

<div class = "site-error">
   <h2>customized error</h2>
   <h1><?= Html::encode($this->title) ?></h1>
   
   <div class = "alert alert-danger">
      <?= nl2br(Html::encode($message)) ?>
   </div>
   
   <p>
      The above error occurred while the Web server was processing your request.
   </p>
   
   <p>
      Please contact us if you think this is a server error. Thank you.
   </p>
</div>

步驟 9 − 訪問地址https://:8080/index.php?r=site/show-error,您將看到自定義的錯誤檢視。

Error Page

Yii - 身份驗證

驗證使用者身份的過程稱為身份驗證。它通常使用使用者名稱和密碼來判斷使用者是否是他聲稱的那個人。

要使用 Yii 身份驗證框架,您需要:

  • 配置使用者應用程式元件。
  • 實現 yii\web\IdentityInterface 介面。

基本應用程式模板帶有一個內建的身份驗證系統。它使用使用者應用程式元件,如下面的程式碼所示:

<?php
   $params = require(__DIR__ . '/params.php');
   $config = [
      'id' => 'basic',
      'basePath' => dirname(__DIR__),
      'bootstrap' => ['log'],
      'components' => [
         'request' => [
            // !!! insert a secret key in the following (if it is empty) - this
               //is required by cookie validation
            'cookieValidationKey' => 'ymoaYrebZHa8gURuolioHGlK8fLXCKjO',
         ],
         'cache' => [
            'class' => 'yii\caching\FileCache',
         ],
         'user' => [
            'identityClass' => 'app\models\User',
            'enableAutoLogin' => true,
         ],
         //other components...
         'db' => require(__DIR__ . '/db.php'),
      ],
      'modules' => [
         'hello' => [
            'class' => 'app\modules\hello\Hello',
         ],
      ],
      'params' => $params,
   ];
   if (YII_ENV_DEV) {
      // configuration adjustments for 'dev' environment
      $config['bootstrap'][] = 'debug';
      $config['modules']['debug'] = [
         'class' => 'yii\debug\Module',
      ];
      $config['bootstrap'][] = 'gii';
      $config['modules']['gii'] = [
         'class' => 'yii\gii\Module',
      ];
   }
   return $config;
?>

在上述配置中,使用者的身份類配置為 app\models\User。

身份類必須實現yii\web\IdentityInterface,幷包含以下方法:

  • findIdentity() − 使用指定的 User ID 查詢身份類的例項。

  • findIdentityByAccessToken() − 使用指定的訪問令牌查詢身份類的例項。

  • getId() − 返回使用者的 ID。

  • getAuthKey() − 返回用於驗證基於 Cookie 的登入的金鑰。

  • validateAuthKey() − 實現驗證基於 Cookie 的登入金鑰的邏輯。

基本應用程式模板中的 User 模型實現了以上所有功能。使用者資料儲存在$users屬性中:

<?php
   namespace app\models;
   class User extends \yii\base\Object implements \yii\web\IdentityInterface {
      public $id;
      public $username;
      public $password;
      public $authKey;
      public $accessToken;
      private static $users = [
         '100' => [
            'id' => '100',
            'username' => 'admin',
            'password' => 'admin',
            'authKey' => 'test100key',
            'accessToken' => '100-token',
         ],
         '101' => [
            'id' => '101',
            'username' => 'demo',
            'password' => 'demo',
            'authKey' => 'test101key',
            'accessToken' => '101-token',
         ],
      ];
      /**
      * @inheritdoc
      */
      public static function findIdentity($id) {
         return isset(self::$users[$id]) ? new static(self::$users[$id]) : null;
      }
      /**
      * @inheritdoc
      */
      public static function findIdentityByAccessToken($token, $type = null) {
         foreach (self::$users as $user) {
            if ($user['accessToken'] === $token) {
               return new static($user);
            }
         }
         return null;
      }
      /**
      * Finds user by username
      *
      * @param string $username
      * @return static|null
      */
      public static function findByUsername($username) {
         foreach (self::$users as $user) {
            if (strcasecmp($user['username'], $username) === 0) {
               return new static($user);
            }
         }
         return null;
      }
      /**
      * @inheritdoc
      */
      public function getId() {
         return $this->id;
      }
      /**
      * @inheritdoc
      */
      public function getAuthKey() {
         return $this->authKey;
      }
      /**
      * @inheritdoc
      */
      public function validateAuthKey($authKey) {
         return $this->authKey === $authKey;
      }
      /**
      * Validates password 
      *
      * @param string $password password to validate
      * @return boolean if password provided is valid for current user
      */
      public function validatePassword($password) {
         return $this->password === $password;
      }
   }
?>

步驟 1 − 訪問 URL https://:8080/index.php?r=site/login,並使用 admin 作為登入名和密碼登入網站。

Admin Login

步驟 2 − 然後,在 SiteController 中新增一個名為actionAuth()的新函式。

public function actionAuth(){
   // the current user identity. Null if the user is not authenticated.
   $identity = Yii::$app->user->identity;
   var_dump($identity);
   // the ID of the current user. Null if the user not authenticated.
   $id = Yii::$app->user->id;
   var_dump($id);
   // whether the current user is a guest (not authenticated)
   $isGuest = Yii::$app->user->isGuest;
   var_dump($isGuest);
}

步驟 3 − 在 Web 瀏覽器中輸入地址https://:8080/index.php?r=site/auth,您將看到有關admin使用者的詳細資訊。

actionAuth Method

步驟 4 − 要登入和登出使用者,可以使用以下程式碼。

public function actionAuth() {
   // whether the current user is a guest (not authenticated)
   var_dump(Yii::$app->user->isGuest);
   // find a user identity with the specified username.
   // note that you may want to check the password if needed
   $identity = User::findByUsername("admin");
   // logs in the user
   Yii::$app->user->login($identity);
   // whether the current user is a guest (not authenticated)
   var_dump(Yii::$app->user->isGuest);
   Yii::$app->user->logout();
   // whether the current user is a guest (not authenticated)
   var_dump(Yii::$app->user->isGuest);
}

首先,我們檢查使用者是否已登入。如果返回值為false,則透過Yii::$app → user → login()呼叫登入使用者,並使用Yii::$app → user → logout()方法登出他。

步驟 5 − 訪問 URL https://:8080/index.php?r=site/auth,您將看到以下內容。

Verifying User Login

yii\web\User類引發以下事件:

  • EVENT_BEFORE_LOGIN − 在yii\web\User::login()開始時引發

  • EVENT_AFTER_LOGIN − 成功登入後引發

  • EVENT_BEFORE_LOGOUT − 在yii\web\User::logout()開始時引發

  • EVENT_AFTER_LOGOUT − 成功登出後引發

Yii - 授權

驗證使用者是否有足夠許可權執行某些操作的過程稱為授權。Yii 提供了一個 ACF(訪問控制過濾器),這是一種作為yii\filters\AccessControl實現的授權方法。修改 SiteController 的 behaviors() 函式:

public function behaviors() {
   return [
      'access' => [
         'class' => AccessControl::className(),
         'only' => ['about', 'contact'],
         'rules' => [
            [
               'allow' => true,
               'actions' => ['about'],
               'roles' => ['?'],
            ],
            [
               'allow' => true,
               'actions' => ['contact', 'about'],
               'roles' => ['@'],
            ],
         ],
      ],
   ];
}

在上述程式碼中,ACF 作為行為附加。only 屬性指定 ACF 僅應用於 about 和 contact 操作。所有其他操作都不受訪問控制。rules 屬性列出了訪問規則。所有訪客(具有“?”角色)都允許訪問about操作。所有已認證的使用者(具有“@”角色)都允許訪問 contact 和 about 操作。

如果您訪問 URL https://:8080/index.php?r=site/about,您將看到頁面,但如果您開啟 URL https://:8080/index.php?r=site/contact,您將被重定向到登入頁面,因為只有已認證的使用者才能訪問contact操作。

訪問規則支援許多選項:

  • allow − 定義這是“允許”規則還是“拒絕”規則。

  • actions − 定義此規則匹配哪些操作。

  • controllers − 定義此規則匹配哪些控制器。

  • roles − 定義此規則匹配的使用者角色。識別兩個特殊角色:

    • ? − 匹配訪客使用者。

    • @ − 匹配已認證的使用者。

  • ips − 定義此規則匹配的 IP 地址。

  • verbs − 定義此規則匹配的請求方法(POST、GET、PUT 等)。

  • matchCallback − 定義應呼叫的 PHP 可呼叫函式,以檢查是否應應用此規則。

  • denyCallback − 定義當此規則拒絕訪問時應呼叫的 PHP 可呼叫函式。

密碼

步驟 1 − Yii 提供了以下用於處理密碼的便捷方法。

public function actionAuth() {

   $password = "asd%#G3";
   
   //generates password hasg
   $hash = Yii::$app->getSecurity()->generatePasswordHash($password);
   var_dump($hash);
   
   //validates password hash
   if (Yii::$app->getSecurity()->validatePassword($password, $hash)) {
      echo "correct password";
   } else {
      echo "incorrect password";
   }
   
   //generate a token
   $key = Yii::$app->getSecurity()->generateRandomString();
   var_dump($key);
   
   //encrypt data with a secret key
   $encryptedData = Yii::$app->getSecurity()->encryptByPassword("mydata", $key);
   var_dump($encryptedData);
   
   //decrypt data with a secret key
   $data = Yii::$app->getSecurity()->decryptByPassword($encryptedData, $key);
   var_dump($data);
   
   //hash data with a secret key
   $data = Yii::$app->getSecurity()->hashData("mygenuinedata", $key);
   var_dump($data);
   
   //validate data with a secret key
   $data = Yii::$app->getSecurity()->validateData($data, $key);
   var_dump($data);
}

步驟 2 − 輸入 URL https://:8080/index.php?r=site/auth,您將看到以下內容。

Passwords

Yii - 本地化

I18N(國際化)是設計可適應各種語言的應用程式的過程。Yii 提供了全方位的 I18N 功能。

語言環境是一組引數,用於指定使用者的語言和國家/地區。例如,en-US 代表英語語言環境和美國。Yii 提供兩種型別的語言:源語言和目標語言。源語言是應用程式中所有文字訊息的編寫語言。目標語言是應用於向終端使用者顯示內容的語言。

訊息翻譯元件將文字訊息從源語言翻譯成目標語言。要翻譯訊息,訊息翻譯服務必須在訊息源中查詢它。

要使用訊息翻譯服務,您應該:

  • 將要翻譯的文字訊息包裝在 Yii::t() 方法中。
  • 配置訊息源。
  • 在訊息源中儲存訊息。

步驟 1 − Yii::t() 方法可以這樣使用。

echo \Yii::t('app', 'This is a message to translate!');

在上面的程式碼片段中,“app”代表訊息類別。

步驟 2 − 現在,修改config/web.php檔案。

<?php
   $params = require(__DIR__ . '/params.php');
   $config = [
      'id' => 'basic',
      'basePath' => dirname(__DIR__),
      'bootstrap' => ['log'],
      'components' => [
         'request' => [
            // !!! insert a secret key in the following (if it is empty) - this
               //is required by cookie validation
            'cookieValidationKey' => 'ymoaYrebZHa8gURuolioHGlK8fLXCKjO',
         ],
         'cache' => [
            'class' => 'yii\caching\FileCache',
         ],
         'i18n' => [
            'translations' => [
               'app*' => [
                  'class' => 'yii\i18n\PhpMessageSource',
                  'fileMap' => [
                     'app' => 'app.php'
                  ],
               ],
            ],
         ],
         'user' => [
            'identityClass' => 'app\models\User',
            'enableAutoLogin' => true,
         ],
         'errorHandler' => [
            'errorAction' => 'site/error',
         ],
         'mailer' => [
            'class' => 'yii\swiftmailer\Mailer',
            // send all mails to a file by default. You have to set
            // 'useFileTransport' to false and configure a transport
            // for the mailer to send real emails.
            'useFileTransport' => true,
         ],
         'log' => [
            'flushInterval' => 1,
            'traceLevel' => YII_DEBUG ? 3 : 0,
            'targets' => [
               [
                  'class' => 'yii\log\FileTarget',
                  'exportInterval' => 1,
                  'logVars' => [],
               ],
            ],
         ],
         'db' => require(__DIR__ . '/db.php'),
      ],
      // set target language to be Russian
      'language' => 'ru-RU',
      // set source language to be English
      'sourceLanguage' => 'en-US',
      'modules' => [
         'hello' => [
            'class' => 'app\modules\hello\Hello',
         ],
      ],
      'params' => $params,
   ];
   if (YII_ENV_DEV) {
      // configuration adjustments for 'dev' environment
      $config['bootstrap'][] = 'debug';
      $config['modules']['debug'] = [
         'class' => 'yii\debug\Module',
      ];
      $config['bootstrap'][] = 'gii';
      $config['modules']['gii'] = [
         'class' => 'yii\gii\Module',
      ];
   }
   return $config;
?>

在上述程式碼中,我們定義了源語言和目標語言。我們還指定了一個由yii\i18n\PhpMessageSource支援的訊息源。app* 模式表示以 app 開頭的所有訊息類別都必須使用此特定訊息源進行翻譯。在上述配置中,所有俄語翻譯都將位於 messages/ru-RU/app.php 檔案中。

步驟 3 − 現在,建立 messages/ru-RU 目錄結構。在 ru-RU 資料夾內建立一個名為 app.php 的檔案。這將儲存所有 EN → RU 翻譯。

<?php
   return [
      'This is a string to translate!' => 'Эта строка для перевода!'
   ];
?>

步驟 4 − 在 SiteController 中建立一個名為 actionTranslation() 的函式。

public function actionTranslation() {
   echo \Yii::t('app', 'This is a string to translate!');
}

步驟 5 − 在 Web 瀏覽器中輸入 URL https://:8080/index.php?r=site/translation,您將看到以下內容。

Translation

該訊息已翻譯成俄語,因為我們將目標語言設定為 ru-RU。我們可以動態更改應用程式的語言。

步驟 6 − 修改actionTranslation()方法。

public function actionTranslation() {
   \Yii::$app->language = 'en-US';
   echo \Yii::t('app', 'This is a string to translate!');
}

現在,訊息以英語顯示:

Action Translation Method

步驟 7 − 在翻譯後的訊息中,您可以插入一個或多個引數。

public function actionTranslation() {
   $username = 'Vladimir';
   // display a translated message with username being "Vladimir"
   echo \Yii::t('app', 'Hello, {username}!', [
      'username' => $username,
   ]), "<br>";
   $username = 'John';
   // display a translated message with username being "John"
   echo \Yii::t('app', 'Hello, {username}!', [
      'username' => $username,
   ]), "<br>";
   $price = 150;
   $count = 3;
   $subtotal = 450;
   echo \Yii::t('app', 'Price: {0}, Count: {1}, Subtotal: {2}', [$price, $count, $subtotal]);
}

輸出如下。

Translated Message

您可以翻譯整個檢視指令碼,而不是翻譯單個文字訊息。例如,如果目標語言為 ru-RU,並且您想翻譯 views/site/index.php 檢視檔案,則應翻譯該檢視並將其儲存在 views/site/ru-RU 目錄下。

步驟 8 − 建立 views/site/ru-RU 目錄結構。然後,在 ru-RU 資料夾內建立一個名為 index.php 的檔案,其中包含以下程式碼。

<?php
   /* @var $this yii\web\View */
   $this->title = 'My Yii Application';
?>

<div class = "site-index">
   <div class = "jumbotron">
      <h1>Добро пожаловать!</h1>
   </div>
</div>

步驟 9 − 目標語言為 ru-RU,因此,如果您輸入 URL https://:8080/index.php?r=site/index,您將看到包含俄語翻譯的頁面。

Russian Translation

Yii - Gii

Gii 是一個擴充套件,它提供了一個基於 Web 的程式碼生成器,用於生成模型、表單、模組、CRUD 等。

預設情況下,以下生成器可用:

  • 模型生成器 − 為指定的資料庫表生成 ActiveRecord 類。

  • CRUD 生成器 − 生成一個控制器和檢視,這些控制器和檢視為指定的模型實現 CRUD(建立、讀取、更新、刪除)操作。

  • 控制器生成器 − 生成一個新的控制器類,其中包含一個或多個控制器操作及其相應的檢視。

  • 表單生成器 − 生成一個檢視指令碼檔案,該檔案顯示一個表單以收集指定的模型類的輸入。

  • 模組生成器 − 生成 Yii 模組所需的程式碼框架。

  • 擴充套件生成器 − 生成 Yii 擴充套件所需的檔案。

要開啟 gii 生成工具,請在 Web 瀏覽器的位址列中輸入https://:8080/index.php?r=gii:

Generation Tool

準備資料庫

步驟 1 − 建立一個新的資料庫。可以透過以下兩種方式準備資料庫:

  • 在終端執行mysql -u root –p

  • 透過CREATE DATABASE helloworld CHARACTER SET utf8 COLLATE utf8_general_ci;建立一個新的資料庫。

步驟 2 − 在config/db.php檔案中配置資料庫連線。以下配置適用於當前使用的系統。

<?php
   return [
      'class' => 'yii\db\Connection',
      'dsn' => 'mysql:host=localhost;dbname=helloworld',
      'username' => 'vladimir',
      'password' => '12345',
      'charset' => 'utf8',
   ];
?>

步驟 3 − 在根資料夾中執行 ./yii migrate/create test_table。此命令將建立一個用於管理我們資料庫的資料庫遷移。遷移檔案應該出現在專案根目錄的migrations資料夾中。

步驟 4 − 以這種方式修改遷移檔案(在本例中為m160106_163154_test_table.php)。

<?php
   use yii\db\Schema;
   use yii\db\Migration;
   class m160106_163154_test_table extends Migration {
      public function safeUp() {
         $this->createTable("user", [
            "id" => Schema::TYPE_PK,
            "name" => Schema::TYPE_STRING,
            "email" => Schema::TYPE_STRING,
         ]);
         $this->batchInsert("user", ["name", "email"], [
            ["User1", "user1@gmail.com"],
            ["User2", "user2@gmail.com"],
            ["User3", "user3@gmail.com"],
            ["User4", "user4@gmail.com"],
            ["User5", "user5@gmail.com"],
            ["User6", "user6@gmail.com"],
            ["User7", "user7@gmail.com"],
            ["User8", "user8@gmail.com"],
            ["User9", "user9@gmail.com"],
            ["User10", "user10@gmail.com"],
            ["User11", "user11@gmail.com"],
         ]);
      }
      public function safeDown() {
         $this->dropTable('user');
      }
   }
?>

以上遷移建立了一個user表,其中包含以下欄位:id、name和email。它還添加了一些演示使用者。

步驟 5 − 在專案根目錄中執行 ./yii migrate以將遷移應用於資料庫。

步驟 6 − 現在,我們需要為我們的user表建立一個模型。為簡單起見,我們將使用Gii程式碼生成工具。開啟此URL:https://:8080/index.php?r=gii。然後,單擊“模型生成器”標題下的“開始”按鈕。填寫表名(“user”)和模型類(“MyUser”),單擊“預覽”按鈕,最後單擊“生成”按鈕。

Gii Preparing DB

MyUser模型應該出現在models目錄中。

Gii - 建立模型

要在 Gii 中建立模型:

<?php
   namespace app\models;
   use app\components\UppercaseBehavior;
   use Yii;
   /**
   * This is the model class for table "user".
   *
   * @property integer $id
   * @property string $name
   * @property string $email
   */
   class MyUser extends \yii\db\ActiveRecord {
      /**
      * @inheritdoc
      */
      public static function tableName() {
         return 'user';
      }
      /**
      * @inheritdoc
      */
      public function rules() {
         return [
            [['name', 'email'], 'string', 'max' => 255]
         ];
      }
      /**
      * @inheritdoc
      */
      public function attributeLabels() {
         return [
            'id' => 'ID',
            'name' => 'Name',
            'email' => 'Email',
         ];
      }
   }
?>

生成 CRUD

讓我們為 MyUser 模型生成 CRUD。

步驟 1 − 開啟 CRUD 生成器介面,填寫表單。

Crud Generator Interface

步驟 2 − 然後,單擊“預覽”按鈕和“生成”。訪問 URL https://:8080/index.php?r=my-user,您將看到所有使用者的列表。

Click Preview Button

步驟 3 − 開啟 URL https://:8080/index.php?r=my-user/create。您應該看到一個使用者建立表單。

User Create Form

Gii - 生成控制器

讓我們看看如何生成控制器。

步驟 1 − 要生成一個包含多個操作的控制器,開啟控制器生成器介面並填寫表單。

Generate Controller

步驟 2 − 然後,點選“預覽”按鈕和“生成”。包含 index、hello 和 world 操作的 CustomController.php 檔案將生成在 controllers 資料夾中。

<?php
   namespace app\controllers;
   class CustomController extends \yii\web\Controller {
      public function actionHello() {
         return $this->render('hello');
      }
      public function actionIndex() {
         return $this->render('index');
      }
      public function actionWorld() {
         return $this->render('world');
      }
   }
?>

表單生成

步驟 1 − 要從現有的模型生成檢視檔案,開啟表單生成介面並填寫表單。

Form Generation

然後,點選“預覽”按鈕和“生成”。customview 檢視檔案將生成在 view 資料夾中。

步驟 2 − 要顯示它,請在 CustomController 中新增一個新方法。

public function actionView() {
   $model = new MyUser();
   return $this->render('/customview', [
      'model' => $model,
   ]);
}

步驟 3 − 要檢視生成的檢視檔案,開啟 URL https://:8080/index.php?r=custom/view

Generated View File

Gii - 生成模組

讓我們看看如何生成一個模組。

步驟 1 − 要生成一個模組,開啟模組生成介面並填寫表單。

Module generator

步驟 2 − 然後,點選“預覽”按鈕和“生成”。

步驟 3 − 我們需要啟用該模組。修改 config/web.php 檔案中的 modules 應用程式元件。

'modules' => [
   'admin' => [
      'class' => 'app\modules\admin\Module',
   ],
],

步驟 4 − 要檢查我們新生成的模組是否有效,請在 Web 瀏覽器中輸入 UR https://:8080/index.php?r=admin/default/index

Generated module Works
廣告