0 關注者

Html 輔助函數

每個 Web 應用程式都會產生大量的 HTML 標記。如果標記是靜態的,則可以透過在單一檔案中混合 PHP 和 HTML 來有效完成,但是當它是動態產生時,在沒有額外協助的情況下處理它會變得棘手。 Yii 以 Html 輔助函數的形式提供此類協助,它提供一組靜態方法來處理常用的 HTML 標籤、它們的選項及其內容。

注意:如果您的標記幾乎是靜態的,則最好直接使用 HTML。沒有必要將所有內容都包裝在 Html 輔助函數呼叫中。

基礎

由於透過字串串接建立動態 HTML 可能很快變得混亂,因此 Yii 提供了一組方法來操作標籤選項並根據這些選項建立標籤。

產生標籤

產生標籤的程式碼如下所示

<?= Html::tag('p', Html::encode($user->name), ['class' => 'username']) ?>

第一個參數是標籤名稱。第二個參數是要封閉在開始和結束標籤之間的內容。請注意,我們正在使用 Html::encode — 這是因為內容不會自動編碼,以便在需要時可以使用 HTML。第三個參數是 HTML 選項陣列,或者換句話說,標籤屬性。在此陣列中,鍵是屬性的名稱(例如 classhreftarget),值是其值。

上面的程式碼將產生以下 HTML

<p class="username">samdark</p>

如果您只需要開始或結束標籤,可以使用 Html::beginTag()Html::endTag() 方法。

選項用於 Html 輔助函數和各種小部件的許多方法中。在所有這些情況下,都有一些額外的處理需要了解

  • 如果值為 null,則不會呈現對應的屬性。
  • 值為布林類型的屬性將被視為布林屬性
  • 屬性的值將使用 Html::encode() 進行 HTML 編碼。
  • 如果屬性的值是陣列,則將按如下方式處理

    • 如果屬性是 yii\helpers\Html::$dataAttributes 中列出的資料屬性,例如 datang,則將為值陣列中的每個元素呈現一個屬性列表。例如,'data' => ['id' => 1, 'name' => 'yii'] 產生 data-id="1" data-name="yii";而 'data' => ['params' => ['id' => 1, 'name' => 'yii'], 'status' => 'ok'] 產生 data-params='{"id":1,"name":"yii"}' data-status="ok"。請注意,在後一個範例中,JSON 格式用於呈現子陣列。
    • 如果屬性不是資料屬性,則該值將以 JSON 編碼。例如,['params' => ['id' => 1, 'name' => 'yii'] 產生 params='{"id":1,"name":"yii"}'

形成 CSS 類別與樣式

當為 HTML 標籤建立選項時,我們通常從需要修改的預設值開始。為了新增或移除 CSS 類別,您可以使用以下內容

$options = ['class' => 'btn btn-default'];

if ($type === 'success') {
    Html::removeCssClass($options, 'btn-default');
    Html::addCssClass($options, 'btn-success');
}

echo Html::tag('div', 'Pwede na', $options);

// if the value of $type is 'success' it will render
// <div class="btn btn-success">Pwede na</div>

您也可以使用陣列樣式指定多個 CSS 類別

$options = ['class' => ['btn', 'btn-default']];

echo Html::tag('div', 'Save', $options);
// renders '<div class="btn btn-default">Save</div>'

您也可以在使用陣列樣式新增或移除類別時使用

$options = ['class' => 'btn'];

if ($type === 'success') {
    Html::addCssClass($options, ['btn-success', 'btn-lg']);
}

echo Html::tag('div', 'Save', $options);
// renders '<div class="btn btn-success btn-lg">Save</div>'

Html::addCssClass() 可防止重複,因此您不必擔心同一個類別出現兩次

$options = ['class' => 'btn btn-default'];

Html::addCssClass($options, 'btn-default'); // class 'btn-default' is already present

echo Html::tag('div', 'Save', $options);
// renders '<div class="btn btn-default">Save</div>'

如果 CSS 類別選項是使用陣列樣式指定的,您可以使用的具名鍵來標記類別的邏輯目的。在這種情況下,在陣列樣式中具有相同鍵的類別將在 Html::addCssClass() 中被忽略

$options = [
    'class' => [
        'btn',
        'theme' => 'btn-default',
    ]
];

Html::addCssClass($options, ['theme' => 'btn-success']); // 'theme' key is already taken

echo Html::tag('div', 'Save', $options);
// renders '<div class="btn btn-default">Save</div>'

CSS 樣式可以使用 style 屬性以類似的方式設定

$options = ['style' => ['width' => '100px', 'height' => '100px']];

// gives style="width: 100px; height: 200px; position: absolute;"
Html::addCssStyle($options, 'height: 200px; position: absolute;');

// gives style="position: absolute;"
Html::removeCssStyle($options, ['width', 'height']);

當使用 addCssStyle() 時,您可以指定鍵值對陣列(對應於 CSS 屬性名稱和值),或字串(例如 width: 100px; height: 200px;)。這些格式可以使用 cssStyleFromArray()cssStyleToArray() 在彼此之間轉換。removeCssStyle() 方法接受要移除的屬性陣列。如果是單一屬性,則可以指定為字串。

編碼與解碼內容

為了使內容在 HTML 中正確且安全地顯示,內容中的特殊字元應進行編碼。在 PHP 中,這是透過 htmlspecialcharshtmlspecialchars_decode 完成的。直接使用這些方法的問題是,您必須始終指定編碼和額外的標誌。由於這些標誌始終相同,並且編碼應與應用程式的編碼相符,以防止安全問題,因此 Yii 提供了兩種簡潔且易於使用的方法

$userName = Html::encode($user->name);
echo $userName;

$decodedUserName = Html::decode($userName);

表單

處理表單標記非常重複且容易出錯。因此,有一組方法可以幫助處理它們。

注意:如果您正在處理模型並且需要驗證,請考慮使用 ActiveForm

建立表單

可以使用 beginForm() 方法開啟表單,如下所示

<?= Html::beginForm(['order/update', 'id' => $id], 'post', ['enctype' => 'multipart/form-data']) ?>

第一個參數是表單將提交到的 URL。它可以 Yii 路由和 Url::to() 接受的參數的形式指定。第二個參數是要使用的方法。post 是預設值。第三個參數是表單標籤的選項陣列。在本例中,我們將 POST 請求中表單資料的編碼變更為 multipart/form-data,這是上傳檔案所必需的。

關閉表單標籤很簡單

<?= Html::endForm() ?>

按鈕

為了產生按鈕,您可以使用以下程式碼

<?= Html::button('Press me!', ['class' => 'teaser']) ?>
<?= Html::submitButton('Submit', ['class' => 'submit']) ?>
<?= Html::resetButton('Reset', ['class' => 'reset']) ?>

所有三種方法的第一個參數是按鈕標題,第二個參數是選項陣列。標題未編碼,因此如果您要顯示來自終端使用者的資料,請使用 Html::encode() 對其進行編碼。

輸入欄位

有兩組輸入方法。以 active 開頭的方法稱為主動輸入,而不以它開頭的方法。主動輸入從模型和指定的屬性中取得資料,而在一般輸入的情況下,資料是直接指定的。

最通用的方法是

type, input name, input value, options
<?= Html::input('text', 'username', $user->name, ['class' => $username]) ?>

type, model, model attribute name, options
<?= Html::activeInput('text', $user, 'name', ['class' => $username]) ?>

如果您事先知道輸入類型,則使用快捷方法會更方便

單選按鈕和核取方塊在方法簽章方面略有不同

<?= Html::radio('agree', true, ['label' => 'I agree']) ?>
<?= Html::activeRadio($model, 'agree', ['class' => 'agreement']) ?>

<?= Html::checkbox('agree', true, ['label' => 'I agree']) ?>
<?= Html::activeCheckbox($model, 'agree', ['class' => 'agreement']) ?>

下拉式清單和列表方塊可以像以下方式呈現

<?= Html::dropDownList('list', $currentUserId, ArrayHelper::map($userModels, 'id', 'name')) ?>
<?= Html::activeDropDownList($users, 'id', ArrayHelper::map($userModels, 'id', 'name')) ?>

<?= Html::listBox('list', $currentUserId, ArrayHelper::map($userModels, 'id', 'name')) ?>
<?= Html::activeListBox($users, 'id', ArrayHelper::map($userModels, 'id', 'name')) ?>

第一個參數是輸入的名稱,第二個參數是目前選取的值,第三個參數是鍵值對陣列,其中陣列鍵是列表值,陣列值是列表標籤。

如果您希望可以選取多個選項,則可以使用核取方塊列表

<?= Html::checkboxList('roles', [16, 42], ArrayHelper::map($roleModels, 'id', 'name')) ?>
<?= Html::activeCheckboxList($user, 'role', ArrayHelper::map($roleModels, 'id', 'name')) ?>

如果不是,請使用單選按鈕列表

<?= Html::radioList('roles', [16, 42], ArrayHelper::map($roleModels, 'id', 'name')) ?>
<?= Html::activeRadioList($user, 'role', ArrayHelper::map($roleModels, 'id', 'name')) ?>

標籤與錯誤

與輸入相同,有兩種方法可以產生表單標籤。主動式,從模型取得資料,以及非主動式,直接接受資料

<?= Html::label('User name', 'username', ['class' => 'label username']) ?>
<?= Html::activeLabel($user, 'username', ['class' => 'label username']) ?>

為了以摘要形式顯示來自一個或多個模型的表單錯誤,您可以使用

<?= Html::errorSummary($posts, ['class' => 'errors']) ?>

若要顯示個別錯誤

<?= Html::error($post, 'title', ['class' => 'error']) ?>

輸入名稱與值

有些方法可以根據模型取得輸入欄位的名稱、ID 和值。這些方法主要在內部使用,但有時可能很方便

// Post[title]
echo Html::getInputName($post, 'title');

// post-title
echo Html::getInputId($post, 'title');

// my first post
echo Html::getAttributeValue($post, 'title');

// $post->authors[0]
echo Html::getAttributeValue($post, '[0]authors[0]');

在上面,第一個參數是模型,而第二個參數是屬性表達式。在其最簡單的形式中,表達式只是一個屬性名稱,但它可以是一個屬性名稱,其前綴和/或後綴帶有陣列索引,這主要用於表格輸入

  • [0]content 用於表格資料輸入中,表示表格輸入中第一個模型的 content 屬性;
  • dates[0] 表示 dates 屬性的第一個陣列元素;
  • [0]dates[0] 表示表格輸入中第一個模型的 dates 屬性的第一個陣列元素。

為了取得不帶後綴或前綴的屬性名稱,可以使用以下方法

// dates
echo Html::getAttributeName('dates[0]');

樣式與腳本

有兩種方法可以產生包裝嵌入樣式和腳本的標籤

<?= Html::style('.danger { color: #f00; }', ['media' => 'print']) ?>

Gives you

<style media="print">.danger { color: #f00; }</style>


<?= Html::script('alert("Hello!");') ?>

Gives you

<script>alert("Hello!");</script>

如果您想在 CSS 檔案中使用外部樣式

<?= Html::cssFile('@web/css/ie5.css', ['condition' => 'IE 5']) ?>

generates

<!--[if IE 5]>
    <link href="https://example.com/css/ie5.css" />
<![endif]-->

第一個參數是 URL。第二個參數是選項陣列。除了常規選項外,您還可以指定

  • condition 使用指定的條件將 <link 包裝在條件註解中。希望您永遠不需要條件註解 ;)
  • noscript 可以設定為 true,以將 <link 包裝在 <noscript> 標籤中,以便僅在瀏覽器中沒有 JavaScript 支援或使用者停用 JavaScript 時才包含它。

若要連結 JavaScript 檔案

<?= Html::jsFile('@web/js/main.js') ?>

與 CSS 相同,第一個參數指定要包含的檔案的 URL。選項可以作為第二個參數傳遞。在選項中,您可以指定 condition,方式與 cssFile 的選項相同。

有一種方法可以方便地產生超連結

<?= Html::a('Profile', ['user/view', 'id' => $id], ['class' => 'profile-link']) ?>

第一個參數是標題。它未編碼,因此如果您使用使用者輸入的資料,則需要使用 Html::encode() 對其進行編碼。第二個參數將是 <a 標籤的 href 屬性中的內容。請參閱 Url::to(),以取得有關其接受的值的詳細資訊。第三個參數是標籤屬性陣列。

如果您需要產生 mailto 連結,可以使用以下程式碼

<?= Html::mailto('Contact us', 'admin@example.com') ?>

圖片

為了產生圖片標籤,請使用以下內容

<?= Html::img('@web/images/logo.png', ['alt' => 'My logo']) ?>

generates

<img src="https://example.com/images/logo.png" alt="My logo" />

除了別名之外,第一個參數可以接受路由、參數和 URL,方式與 Url::to() 相同。

列表

無序列表可以像以下方式產生

<?= Html::ul($posts, ['item' => function($item, $index) {
    return Html::tag(
        'li',
        $this->render('post', ['item' => $item]),
        ['class' => 'post']
    );
}]) ?>

為了取得有序列表,請改用 Html::ol()

發現錯字或您認為此頁面需要改進?
在 github 上編輯 !