PHP笔记——Yii2学习笔记4(视图入门之布局,前端资源)

       这一篇主要讲视图的一些入门的相关内容,Yii的中文网站,对应的教程文档中,也有视图的相关介绍,不过内容较多,从创建视图、页面安全、渲染视图、视图数据、视图布局、数据块、视图组件、视图事件,基本把视图的所有相关的都有介绍,但是都很精简,初学者初看一下,容易被吓退,Yii2的学习成本真高。这里,从一个简单的网站项目角度,我们来看如何应用Yii2框架。

一个新的网站,从功能或者应用场景出发,一般我把网站分为以下几个大类:

  1. 公司官网,以静态页面,以及部分动态页面(新闻公告等)为主,无需太多权限控制。
  2. 博客,留言板,论坛类网站,以动态数据为主,功能较为单一,只需要简单的权限控制。
  3. 电商平台、公司OA平台类网站,功能复杂,业务多样,需要可动态配置的权限设定。

但无论哪一种网站,第一步考虑布局,而复杂的网站,下一步考虑就是权限设计,这两者基本可以说是网站的两个方面的框架,布局定义的是UI交互框架,权限设计定义的是底层业务框架。

相关源码,可以去gitee上下载: yii2_study: 学习yii2的各种组件应用示例

一、视图布局

Yii框架中,布局的应用还是较为简单的,并且能够支持嵌套布局。这里,我们设想一个简单的管理端网站,说穿了,快速搭建一个后台管理端网站方面是PHP的擅长领域。

一个管理端网站,简单考虑,总有登录页面,也有菜单功能页面,这两种页面,在页面布局方面,是完全截然不同的两种布局,但是,对我网站而言,再不同的布局,也是有相同部分的,例如,使用的字符编码等,或者是否打算支持自适应,或者是否有共同的样式文件,JS框架文件等,所以打算采用嵌套式的布局,即最底层的布局文件自包含最简单的共通部分。

1.1. 基础布局文件 base.php

布局文件默认路径是views/layouts 下,当然也可以改目录,这里我们先在layouts下新建一个base.php文件,作为基础布局文件。

<?php

/* @var $this \yii\web\View */
/* @var $content string */

use app\assets\WebAsset;
use yii\bootstrap4\Html;

WebAsset::register($this);

$this->beginPage();
?>
<!DOCTYPE html>
<html lang="<?= Yii::$app->language ?>" class="h-100">

<head>
    <meta charset="<?= Yii::$app->charset ?>">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimal-ui">
    <meta name="keywords" content="yii2,php,yii2-study">
    <meta name="author" content="Myron.Maoyz">
    <?php $this->registerCsrfMetaTags() ?>
    <title><?= Html::encode($this->title) ?></title>
    <?php $this->head() ?>
</head>

<body class="d-flex flex-column h-100">
    <?php $this->beginBody() ?>

    <?= $content ?>

    <?php $this->endBody() ?>
</body>

</html>
<?php $this->endPage() ?>

布局文件的核心,就是 <?= $content ?> ,凡是引用了这个布局文件的视图文件,视图内容将会替代的就是这句语句。除了<?= $content ?>这句,整个布局文件,上下还有几句beginXXX,endXXX的语句,这些都是布局文件中必须要用的,根据官方介绍,这些语句将会触发前端资源加载事件,所谓的前端资源,可以看第二部分前端资源的说明。

1.2. 登录页面布局 bottom.php

一般管理端网站的登录页都是很简单的,直接基于基础布局应用就行,这里,为了简单说明一下嵌套布局,新建一个上下两层的布局,就是多了一个footer的布局。

<?php $this->beginContent('@app/views/layouts/base.php'); ?>


<main role="main">
    <div class="container">
        <?= $content ?>
    </div>
</main>

<footer class="footer text-muted">
    <div class="container">
        <p class="float-left">&copy; Yii-Study <?= date('Y') ?></p>
    </div>
</footer>
<style>
    main {
        position: absolute;
        height: 100%;
        width: 100%;
        bottom: 42px;
        background-color: mintcream;
    }

    main>.container {
        padding: 0;
        background: no-repeat center 0px;
        background-size: cover;
        height: 100%;
    }

    .footer {
        position: absolute;
        bottom: 0;
        background-color: #3a3a3a;
        font-size: .9em;
        height: 42px;
        width: 100%;
    }

    .footer>.container {
        padding-right: 15px;
        padding-left: 15px;
        max-width: 800px;
    }

    .footer>.container>p {
        padding-top: 10px;
    }
</style>
<?php $this->endContent(); ?>

在上面这个布局文件中,我们引用了base.php的布局,并在上面进行了扩展,这就是嵌套布局。

1.3. 布局应用

创建了布局后,需要在类文件,或动作函数中,进行指定布局文件,否则默认只会加载main.php的布局。我们在controllers目录下创建Demo2类文件,如下

<?php

namespace app\controllers;

class Demo2Controller extends \yii\web\Controller
{

    public function actionIndex()
    {
        $this->layout = "bottom";

        return $this->render('index');
    }
}

我们继续在对应的视图目录views/demo2下,创建对应的视图文件index.php,如下

<div class="bg-translucent p-2 center-vh">
    <div class="flex-box bg-white login-box shadow-lg border border-success">
        <div class="login-right p-5 d-none d-sm-block">
            <p class="mb-3">
            <h3>Yii2-Study Demo</h3>
            </p>
            <p class="text-white">基于Yii框架2.0.43版,参考Light Year Admin的模版。</p>

        </div>
        <div class="login-left p-5 ">
            <div class="form-group has-feedback">
                <span>帐号:</span>
                <input type="text" class="form-control" id="username">
            </div>

            <div class="form-group has-feedback">
                <span>密码:</span>
                <input type="password" class="form-control" id="password">
            </div>

            <div class="form-group mt-auto">
                <button class="btn btn-block btn-primary" type="submit">立即登录</button>
            </div>
        </div>

    </div>
</div>
<style>
    .login-form .has-feedback {
        position: relative;
    }

    .login-form .has-feedback .form-control {
        padding-left: 36px;
    }

    .login-form .has-feedback .mdi {
        position: absolute;
        top: 0;
        left: 0;
        right: auto;
        width: 36px;
        height: 36px;
        line-height: 36px;
        z-index: 4;
        color: #dcdcdc;
        display: block;
        text-align: center;
        pointer-events: none;
    }

    .login-form .has-feedback.row .mdi {
        left: 15px;
    }

    .login-form .form-group:last-child,
    .login-right p:last-child {
        margin-bottom: 0px;
    }

    .login-right {
        background: #67b26f !important;
        background: -moz-linear-gradient(45deg, #67b26f 0, #4ca2cd 100%) !important;
        background: -webkit-linear-gradient(45deg, #67b26f 0, #4ca2cd 100%) !important;
        background: linear-gradient(45deg, #67b26f 0, #4ca2cd 100%) !important;
        filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#67b26f', endColorstr='#4ca2cd', GradientType=1) !important;
    }

    .login-box {
        max-width: 700px;
    }

    .login-right {
        width: 50%;
    }

    .login-left {
        width: 50%;
        height: 100%;
    }
</style>

1.4. 结果

通过浏览器访问链接: http://localhost/yii2_study/web/index.php?r=demo2

二、前端资源

所谓的前端资源,在Yii2的定义中,被认为是和视图Web相关的Js,Css等文件资源,可以是在web目录下,可以直接通过url访问,也可以是在web目录外,需要在调用的时候发布到web目录下后,才能被调用。还有一种就是其他服务器上的资源,可以是开放的第三方资源,可以是负载服务器上的资源。

这里,还是先介绍简单的一些资源的常规使用方式,如Yii2的很多封装的小部件,都是基于JQuery和Bootstrap框架下才能正常运行,所以就需要在最基础的布局中,加载这些框架文件。

2.1. 布局文件加载资源

一般来说,资源加载类独立会有一个目录assets,类名常规也会是XXXAsset.php,但这个不是强制规定,都可以随意改,不同Controller类名那样强制要求,但是必须继承 yii\web\AssetBundle 类。这里,我们以上面的 assets/WebAsset.php 类进行说明。

<?php

namespace app\assets;

use yii\web\AssetBundle;

class WebAsset extends AssetBundle
{
    public $basePath = '@webroot';
    public $baseUrl = '@web';
    public $css = [
        'css/style.min.css',
    ];
    public $js = [];
    public $depends = [
        'yii\web\YiiAsset',
        'yii\bootstrap4\BootstrapAsset',
    ];

    public $jsOptions = [
        'position' => \yii\web\View::POS_HEAD
    ];
}

      上面的代码中,$basePath指文件路径 , $baseUrl指该文件的Url访问路径,$css就包含了一个文件 'css/style.min.css',这里结合basePath的值,表示css文件的全路径应该是 web/css/style.min.css 。$js目前没有值,但实际文件路径的方式和css是一致的。

       但是,我们知道,Js,Css在html中的顺序很重要,js中有依赖性,css中存在后续的css会覆盖之前的css,$depends就是用来梳理顺序的。

       Yii2框架中,加载Js,Css文件中,有几个默认的顺序,就是CSS默认加载在<head>标签中,Js默认加载<body>尾部,也就是说上面的代码,没有设定 'position' => \yii\web\View::POS_HEAD 所有的js文件会出现在<body>尾部,这里简单介绍一下YiiAsset、BootstrapAsset这两个类,基本就是一个加载Jquery框架,一个加载Bootstrap框架,而我们如果在视图文件中,用到jquery的函数,如果在手动加载jquery就会出现重复加载,如果不加载,就会报错,所以,我们需要让一些第三方的框架文件在<head>标签内加载,而页面的js则随着页面部分加载。

2.2 嵌套布局的资源加载

之前,我们介绍了布局,嵌套的布局方案,那么嵌套的布局的资源如何加载呢?我们假设一个场景,最底层的布局文件,如同上面的base.php,无关任何布局风格,仅设定了字符集,以及一部分的Meta设置,但指定了基本的jquery框架,bootstrap的引用。基于底层的base布局,会分出多种布局,如上下层的登录页布局,上中下的菜单布局模式等,各自加载了不同的第三方样式框架和JS框架,或者自行编写的通用JS文件。

Yii2提供了多种方式实现资源文件的加载。

方式一:

先说一种最简单粗暴的方式,在视图文件,或者布局文件中,直接一个文件一个文件自己排序加载。

<?php

use yii\helpers\Html;

?>


.....

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

<?= Html::cssFile('@web/.../css/xxxx.css') ?> 

....


优点:直接、直观、随意。

缺点:散在各个文件中,繁琐,加载的文件只能是web目录下的文件。

这种方式一般用于实际业务的具体视图文件中,因为特定功能,需要加载第三方的插件资源,如图表类js,css这种。

方式二:

通过之前介绍的 yii\web\AssetBundle 类,来实现资源加载。我们给基础布局base.php分配AppAsset.php,给子布局bottom.php分配WebAsset.php,我们在实际的视图文件中,用方式一的方法,加载视图的js,css文件。

我们先看两个资源加载类:assets/AppAsset.phpassets/WebAsset.php

<?php

/**
 * @link http://www.yiiframework.com/
 * @copyright Copyright (c) 2008 Yii Software LLC
 * @license http://www.yiiframework.com/license/
 */

namespace app\assets;

use yii\web\AssetBundle;

/**
 * Main application asset bundle.
 *
 * @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\bootstrap4\BootstrapAsset',
    ];

    public $jsOptions = [
        // POS_HEAD 指向<head>标签内,$this->head() 函数的位置
        // POS_BEGIN 指向<body>标签后面的位置
        // POS_END 指向</body>标签前面的位置
        'position' => \yii\web\View::POS_HEAD
    ];
}
<?php

namespace app\assets;

use yii\web\AssetBundle;

class WebAsset extends AssetBundle
{
    public $basePath = '@webroot';
    public $baseUrl = '@web';
    public $css = [
        'css/style.min.css',
    ];
    public $js = [
        'js/main.min.js'
    ];


    // 通过不同的加载位置,区分先后
    public $jsOptions = ['position' => \yii\web\View::POS_BEGIN];

    // 父布局引用的资源分配类,有相同的依赖,那么position必须相同,才能配置$depends,否则报错
    // public $depends = [
    //     'yii\web\YiiAsset',
    //     'yii\bootstrap4\BootstrapAsset',
    // ];
}

再来修正两个布局文件 views/layouts/base.phpviews/layouts/bottom.php

<?php

/* @var $this \yii\web\View */
/* @var $content string */

use app\assets\AppAsset;
use yii\bootstrap4\Html;

AppAsset::register($this);

$this->beginPage();
?>
<!DOCTYPE html>
<html lang="<?= Yii::$app->language ?>" class="h-100">

<head>
    <meta charset="<?= Yii::$app->charset ?>">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimal-ui">
    <meta name="keywords" content="yii2,php,yii2-study">
    <meta name="author" content="Myron.Maoyz">
    <?php $this->registerCsrfMetaTags() ?>
    <?php $this->head() // 输出定向到POS_HEAD的资源文件
    ?>
    <title><?= Html::encode($this->title) ?></title>

</head>

<body class="d-flex flex-column h-100">
    <?php $this->beginBody()
    ?>

    <?= $content ?>

    <?php $this->endBody()
    ?>
</body>

</html>
<?php $this->endPage()
?>
<?php

/* @var $this \yii\web\View */
/* @var $content string */

use app\assets\WebAsset;

WebAsset::register($this);

?>
<?php $this->beginContent('@app/views/layouts/base.php'); ?>

<main role="main">
    <div class="container">
        <?= $content ?>
    </div>
</main>

<footer class="footer text-muted">
    <div class="container">
        <p class="float-left">&copy; Yii-Study <?= date('Y') ?></p>
    </div>
</footer>
<style>
    main {
        position: absolute;
        height: 100%;
        width: 100%;
        bottom: 42px;
        background-color: mintcream;
    }

    main>.container {
        padding: 0;
        background: url("./images/bg_welcome.png") no-repeat center 0px;
        background-size: cover;
        height: 100%;
    }

    .footer {
        position: absolute;
        bottom: 0;
        background-color: #3a3a3a;
        font-size: .9em;
        height: 42px;
        width: 100%;
    }

    .footer>.container {
        padding-right: 15px;
        padding-left: 15px;
        max-width: 800px;
    }

    .footer>.container>p {
        padding-top: 10px;
    }
</style>
<?php $this->endContent(); ?>

最后,我们来修改一下视图文件 views\demo2\index.php

<?php

/* @var $this \yii\web\View */
/* @var $content string */

use yii\helpers\Html;

echo Html::jsFile('@web/js/main.min.js');   //这里***代表你的目录名或者文件名
echo Html::cssFile('@web/css/animate.min.css');    //***同上


?>
<div class="bg-translucent p-2 center-vh">
    <div class="flex-box bg-white login-box shadow-lg border border-success">
        <div class="login-right p-5 d-none d-sm-block">
            <p class="mb-3">
            <h3>Yii2-Study Demo</h3>
            </p>
            <p class="text-white">基于Yii框架2.0.43版,参考Light Year Admin的模版。</p>

        </div>
        <div class="login-left p-5 ">
            <div class="form-group has-feedback">
                <span>帐号:</span>
                <input type="text" class="form-control" id="username">
            </div>

            <div class="form-group has-feedback">
                <span>密码:</span>
                <input type="password" class="form-control" id="password">
            </div>

            <div class="form-group mt-auto">
                <button class="btn btn-block btn-primary" type="submit">立即登录</button>
            </div>
        </div>

    </div>
</div>
<style>
    .login-form .has-feedback {
        position: relative;
    }

    .login-form .has-feedback .form-control {
        padding-left: 36px;
    }

    .login-form .has-feedback .mdi {
        position: absolute;
        top: 0;
        left: 0;
        right: auto;
        width: 36px;
        height: 36px;
        line-height: 36px;
        z-index: 4;
        color: #dcdcdc;
        display: block;
        text-align: center;
        pointer-events: none;
    }

    .login-form .has-feedback.row .mdi {
        left: 15px;
    }

    .login-form .form-group:last-child,
    .login-right p:last-child {
        margin-bottom: 0px;
    }

    .login-right {
        background: #67b26f !important;
        background: -moz-linear-gradient(45deg, #67b26f 0, #4ca2cd 100%) !important;
        background: -webkit-linear-gradient(45deg, #67b26f 0, #4ca2cd 100%) !important;
        background: linear-gradient(45deg, #67b26f 0, #4ca2cd 100%) !important;
        filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#67b26f', endColorstr='#4ca2cd', GradientType=1) !important;
    }

    .login-box {
        max-width: 700px;
    }

    .login-right {
        width: 50%;
    }

    .login-left {
        width: 50%;
        height: 100%;
    }
</style>

我们来看一下效果

 我们发现,子布局bottom中没有指定css的加载位置,默认就是<head>标签,但是子布局的资源文件在没有配置依赖的前提下,是会排在父布局base的资源前面的。

如果希望子布局bottom中的css加载位置在父布局的css后面,一种是在WebAsset.php中指定$cssOptions的位置,同样是POS_BEGIN或POS_END,另一种,就是在WebAsset中设置依赖$depends,都可以调整顺序。


上面将的布局和前端资源都是基本的应用方式,Yii2框架还有支持更多的配置,如资源包的整合发布等等,在了解了基本原理后,可以参考官方网站进一步研究。

参考:

应用结构(Application Structure): 视图(Views) - Yii 2.0 权威指南 - 文档 - Yii Framework 中文网

关于Yii2中CSS,JS文件的引入心得 - 教程 - Yii Framework 中文网

应用结构(Application Structure): 前端资源(Assets) - Yii 2.0 权威指南 - 文档 - Yii Framework 中文网

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值