YII框架yiic、gii工具使用方法

yiic自動代碼生成

yiic是自動代碼生成工具,可以生成應用基本框架。假設YiiRoot爲Yii的安裝目錄,AppRoot(不用創建,將自動生成)爲即將安裝的YiiRoot下的目錄,則在dos命令行中運行yiic命令即可完成框架的自動生成。
YiiRoot/framework/yiic webapp YiiRoot/AppRoot
注意: 在 MacOS、Linux 或 Unix 系統中運行  yiic 時,你可能需要修改  yiic 文件的權限使它能夠運行。你也可以用  php YiiRoot/framework/yiic.php 來代替  yiic。
這將在  WebRoot
/AppRoot目錄下建立一個最基本的 Yii 應用,WebRoot 代表你的 Web 服務器根目錄。這
個應用具有所有必須的目錄和文件,因此可以方便地在此基礎上添加更多功能。

 

gii自動代碼生成

自版本 1.1.2 起, Yii 裝備了基於 Web 界面的代碼生成工具Gii。 它取代了之前的命令行端的代碼生成工具 yiic shell。 在這部分,我們將講解如何使用 Gii 以及如何擴展 Gii 以增加我們的開發成果。

1. 使用 Gii 

Gii 是以模塊的方式實現的,它必須在一個已存在的 Yii 應用程序中使用。要使用 Gii,我們首先更改應用程序的配置如下:

return array(
    ......
    'modules'=>array(
        'gii'=>array(
            'class'=>'system.gii.GiiModule',
            'password'=>'在這裏填寫密碼',
            // 'ipFilters'=>array(...IP 列表...),
            // 'newFileMode'=>0666,
            // 'newDirMode'=>0777,
        ),
    ),
);

在上面,我們聲明瞭一個名爲 gii 的模塊,它的類是 GiiModule。我們也爲這個模塊設置了一個密碼,我們訪問 Gii 時會有一個輸入框要求填寫這個密碼。

出於安全考慮,默認情況下只允許本機訪問 Gii。若允許其他可信賴的機器訪問它,我們需要如上所示配置GiiModule::ipFilters 屬性。

因爲 Gii 會生成並保存新文件到應用程序中,我們需要確保 Web 服務器進程有權限這樣做。上面的GiiModule::newFileMode 和 GiiModule::newDirMode 屬性控制如何生成新文件和新目錄。

注意: Gii 主要用作一個開發工具。因此,應當只在開發機器上安裝它。因爲它可以在應用程序中生成新的 PHP 文件,我們應當對安全問題足夠重視(例如設置密碼,IP 過濾)。

現在可以通過 URL http://hostname/path/to/index.php?r=gii 訪問 Gii 了。(注意此時不要添加url規則,具體可參見http://www.cnblogs.com/tambor/archive/2011/09/10/2172928.html)這裏我們假設http://hostname/path/to/index.php 是訪問 Yii 應用程序的 URL。

若 Yii 應用程序使用 path 格式的 URL (查看 URL management),我們可以通過 URLhttp://hostname/path/to/index.php/gii 訪問 Gii。 我們可能需要增加如下 URL 規則到已有的 URL 規則的前面:

'components'=>array(
    ......
    'urlManager'=>array(
        'urlFormat'=>'path',
        'rules'=>array(
            'gii'=>'gii',
            'gii/<controller:\w+>'=>'gii/<controller>',
            'gii/<controller:\w+>/<action:\w+>'=>'gii/<controller>/<action>',
            ...已有的規則...
        ),
    ),
)

Gii 有一些默認的代碼生成器。每個代碼生成器負責生成特定類型的代碼。例如 controller 生成器生成一個 controller 類以及一些 action view 腳本; model 生成器爲指定的數據表生成一個 ActiveRecord 類。

使用一個生成器的基本流程如下:

  1. 進入生成器頁面;
  2. 填寫指定代碼生成參數的輸入框。例如,使用 Module Generator 創建一個新模塊,你需要指定 module ID;
  3. 點擊 Preview 按鈕預覽即將生成的代碼。你將看到一個表格中列出了將要生成的文件列表。你可以點擊其中任何一個文件來預覽代碼;
  4. 點擊 Generate 按鈕生成這些代碼文件;
  5. 查看代碼生成日誌。

2. 擴展 Gii 

雖然默認的 Gii 代碼生成器可以生成非常強大的代碼,然而我們經常想定製它們或者創建一個新的來適應我們的口味和需求。例如,我們想讓生成的代碼是我們喜歡的風格,或者想讓代碼支持多種語言。所有這些在 Gii 中都可非常容易地實現。

可以 2 種方式擴展 Gii:定製已存在的代碼生成器的代碼模板,以及編寫新的代碼生成器。

代碼生成器的架構

一個代碼生成器存儲在一個目錄中,這個目錄的名字被認爲是生成器的名字。目錄通常由如下內容組成:

model/                       the model generator root folder
   ModelCode.php             the code model used to generate code
   ModelGenerator.php        the code generation controller
   views/                    containing view scripts for the generator
      index.php              the default view script
   templates/                containing code template sets
      default/               the 'default' code template set
         model.php           the code template for generating model class code

生成器搜索路徑

Gii 在GiiModule::generatorPaths 屬性指定的目錄中查找可用的生成器。 當需要定製時,我們可以在應用程序的配置文件中做如下配置,

return array(
    'modules'=>array(
        'gii'=>array(
            'class'=>'system.gii.GiiModule',
            'generatorPaths'=>array(
                'application.gii',   // a path alias
            ),
        ),
    ),
);

上面的配置告訴 Gii 在別名是 application.gii 的目錄中尋找生成器,以及默認的位置system.gii.generators

在不同的搜索路徑有同名的生成器也是可以的。這種情況下,在 GiiModule::generatorPaths 指定目錄中先出現的生成器有優先權。

定製代碼模板

這是擴展 Gii 最容易最常用的方式。我們使用一個例子來介紹如何定製代碼模板。假設我們想要定製由 model 生成器生成的代碼。

我們首先創建一個名爲 protected/gii/model/templates/compact 的目錄。這裏的 model 意味着我們將要override 默認的 model 生成器。 templates/compact 意味着我們將增加一個新的代碼模板集名爲 compact

然後我們在應用程序配置裏把 application.gii 增加到 GiiModule::generatorPaths 。如上所示。

現在打開 model 代碼生成器頁面。點擊 Code Template 輸入框。我們應當看到一個下拉列表,這個列表包含了我們新建的模板目錄 compact。可是,若我們選擇此模板生成代碼,我們將看到錯誤。這是因爲我們還沒有在新的 compact 模板集中放入任何實際的代碼模板文件。

複製文件 framework/gii/generators/model/templates/default/model.php 到protected/gii/model/templates/compact。若我們再次嘗試以 compact 模板生成,我們會成功。但是,生成的代碼和以 default 模板集生成的代碼沒什麼不同。

現在是時候做點真正的工作了。打開文件 protected/gii/model/templates/compact/model.php 以編輯它。記得這個文件將作爲類似一個視圖文件被使用,意味着它可以包含 PHP 表達式和語句。讓我們更改模板以便生成的代碼裏 attributeLabels() 方法使用 Yii::t() 來翻譯屬性標籤:

public function attributeLabels()
{
    return array(
<?php foreach($labels as $name=>$label): ?>
            <?php echo "'$name' => Yii::t('application', '$label'),\n"; ?>
<?php endforeach; ?>
    );
}

在每個代碼模板中,我們可以訪問一些預定義的變量,例如上面例子中的 $labels。這些變量由對應的代碼生成器提供。不同的代碼生成器可能在他們的代碼模板中提供不同的變量。請認真閱讀默認代碼模板中的描述。

創建新的生成器

In this sub-section, we show how to create a new generator that can generate a new widget class.

We first create a directory named protected/gii/widget. Under this directory, we will create the following files:

  • WidgetGenerator.php: contains the WidgetGenerator controller class. This is the entry point of the widget generator.
  • WidgetCode.php: contains the WidgetCode model class. This class has the main logic for code generation.
  • views/index.php: the view script showing the code generator input form.
  • templates/default/widget.php: the default code template for generating a widget class file.

Creating WidgetGenerator.php

The WidgetGenerator.php file is extremely simple. It only contains the following code:

class WidgetGenerator extends CCodeGenerator
{
    public $codeModel='application.gii.widget.WidgetCode';
}

In the above code, we specify that the generator will use the model class whose path alias isapplication.gii.widget.WidgetCode. The WidgetGenerator class extends from CCodeGenerator which implements a lot of functionalities, including the controller actions needed to coordinate the code generation process.

Creating WidgetCode.php

The WidgetCode.php file contains the WidgetCode model class that has the main logic for generating a widget class based on the user input. In this example, we assume that the only input we want from the user is the widget class name. Our WidgetCode looks like the following:

class WidgetCode extends CCodeModel
{
    public $className;
 
    public function rules()
    {
        return array_merge(parent::rules(), array(
            array('className', 'required'),
            array('className', 'match', 'pattern'=>'/^\w+$/'),
        ));
    }
 
    public function attributeLabels()
    {
        return array_merge(parent::attributeLabels(), array(
            'className'=>'Widget Class Name',
        ));
    }
 
    public function prepare()
    {
        $path=Yii::getPathOfAlias('application.components.' . $this->className) . '.php';
        $code=$this->render($this->templatepath.'/widget.php');
 
        $this->files[]=new CCodeFile($path, $code);
    }
}

The WidgetCode class extends from CCodeModel. Like a normal model class, in this class we can declarerules() and attributeLabels() to validate user inputs and provide attribute labels, respectively. Note that because the base class CCodeModel already defines some rules and attribute labels, we should merge them with our new rules and labels here.

The prepare() method prepares the code to be generated. Its main task is to prepare a list of CCodeFileobjects, each of which represent a code file being generated. In our example, we only need to create oneCCodeFile object that represents the widget class file being generated. The new widget class will be generated under the protected/components directory. We call CCodeFile::render method to generate the actual code. This method includes the code template as a PHP script and returns the echoed content as the generated code.

Creating views/index.php

Having the controller (WidgetGenerator) and the model (WidgetCode), it is time for us to create the viewviews/index.php.

<h1>Widget Generator</h1>
 
<?php $form=$this->beginWidget('CCodeForm', array('model'=>$model)); ?>
 
    <div class="row">
        <?php echo $form->labelEx($model,'className'); ?>
        <?php echo $form->textField($model,'className',array('size'=>65)); ?>
        <div class="tooltip">
            Widget class name must only contain word characters.
        </div>
        <?php echo $form->error($model,'className'); ?>
    </div>
 
<?php $this->endWidget(); ?>

In the above, we mainly display a form using the CCodeForm widget. In this form, we display the field to collect the input for the className attribute in WidgetCode.

When creating the form, we can exploit two nice features provided by the CCodeForm widget. One is about input tooltips. The other is about sticky inputs.

If you have tried any default code generator, you will notice that when setting focus in one input field, a nice tooltip will show up next to the field. This can easily achieved here by writing next to the input field a div whose CSS class is tooltip.

For some input fields, we may want to remember their last valid values so that the user can save the trouble of re-entering them each time they use the generator to generate code. An example is the input field collecting the controller base class name default controller generator. These sticky fields are initially displayed as highlighted static text. If we click on them, they will turn into input fields to take user inputs.

In order to declare an input field to be sticky, we need to do two things.

First, we need to declare a sticky validation rule for the corresponding model attribute. For example, the default controller generator has the following rule to declare that baseClass and actions attributes are sticky:

public function rules()
{
    return array_merge(parent::rules(), array(
        ......
        array('baseClass, actions', 'sticky'),
    ));
}

Second, we need to add a CSS class named sticky to the container div of the input field in the view, like the following:

<div class="row sticky">
    ...input field here...
</div>

Creating templates/default/widget.php

Finally, we create the code template templates/default/widget.php. As we described earlier, this is used like a view script that can contain PHP expressions and statements. In a code template, we can always access the $this variable which refers to the code model object. In our example, $this refers to the WidgetModelobject. We can thus get the user-entered widget class name via $this->className.

<?php echo '<?php'; ?>
 
class <?php echo $this->className; ?> extends CWidget
{
    public function run()
    {
 
    }
}

This concludes the creation of a new code generator. We can access this code generator immediately via the URL http://hostname/path/to/index.php?r=gii/widget.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章