[ Laravel 5.3 文档 ] 视图 & 模板 —— 视图

1、 创建视图

视图包含应用的 HTML 代码并将应用的控制器逻辑和表现逻辑进行分离。视图文件存放在 resources/views 目录。

下面是一个简单视图:

<!-- 该视图存放 resources/views/greeting.php -->

<html>
    <body>
        <h1>Hello, {{ $name }}</h1>
    </body>
</html>

由于这个视图存放在 resources/views/greeting.php,我们可以在全局的辅助函数 view 中这样返回它:

Route::get('/', function () {
    return view('greeting', ['name' => 'James']);
});

正如你所看到的,传递给 view 方法的第一个参数是 resources/views 目录下相应的视图文件的名字,第二个参数是一个数组,该数组包含了在该视图中所有有效的数据。在这个例子中,我们传递了一个 name 变量,在视图中通过执行 echo 将其显示出来。

当然,视图还可以嵌套在 resources/views 的子目录中,用“.”号来引用嵌套视图,比如,如果视图存放路径是resources/views/admin/profile.php,那我们可以这样引用它:

return view('admin.profile', $data);

判断视图是否存在

如果需要判断视图是否存在,可调用在不带参数的 view 之后使用 exists 方法,如果视图在磁盘存在则返回true

if (view()->exists('emails.customer')) {
    //
}

调用不带参数的 view 时,将会返回一个 Illuminate\Contracts\View\Factory  实例,从而可以调用该工厂上的所有方法。

2、传递数据到视图

在上述例子中可以看到,我们可以简单通过数组方式将数据传递到视图:

return view('greetings', ['name' => 'Victoria']);

以这种方式传递数据的话,$data 应该是一个键值对数组,在视图中,就可以使用相应的键来访问数据值,比如 <?php echo $key; ?>。除此之外,还可以通过 with 方法添加独立的数据片段到视图:

$view = view('greeting')->with('name', 'Victoria');

在视图间共享数据

有时候我们需要在所有视图之间共享数据片段,这时候可以使用视图工厂的 share 方法,通常,需要在服务提供者的boot 方法中调用 share 方法,你可以将其添加到 AppServiceProvider 或生成独立的服务提供者来存放它们:

<?php

namespace App\Providers;

class AppServiceProvider extends ServiceProvider
{
    /**
     * 启动所有应用服务
     *
     * @return void
     */
    public function boot()
    {
        view()->share('key', 'value');
    }

    /**
     * 注册服务提供者
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

3、视图Composer

视图 Composer 是当视图被渲染时的回调或类方法。如果你有一些数据要在视图每次渲染时都做绑定,可以使用视图 Composer 将逻辑组织到一个单独的地方。

首先要在服务提供者中注册视图 Composer,我们将会使用辅助函数 view 来访问Illuminate\Contracts\View\Factory 的底层实现,记住,Laravel 不会包含默认的视图 Composer 目录,我们可以按照自己的喜好组织其路径,例如可以创建一个 App\Http\ViewComposers 目录:

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class ComposerServiceProvider extends ServiceProvider
{
    /**
     * 在容器中注册绑定.
     *
     * @return void
     * @author http://laravelacademy.org
     */
    public function boot()
    {
        // 使用基于类的composers...
        view()->composer(
            'profile', 'App\Http\ViewComposers\ProfileComposer'
        );

        // 使用基于闭包的composers...
        view()->composer('dashboard', function ($view) {});
    }

    /**
     * 注册服务提供者.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

注:如果创建一个新的服务提供者来包含视图 Composer 注册,需要添加该服务提供者到配置文件 config/app.php 的providers 数组中。

现在我们已经注册了 Composer,每次 profile 视图被渲染时都会执行 ProfileComposer@compose,接下来我们来定义该 Composer 类:

<?php

namespace App\Http\ViewComposers;

use Illuminate\Contracts\View\View;
use Illuminate\Users\Repository as UserRepository;

class ProfileComposer
{
    /**
     * 用户仓库实现.
     *
     * @var UserRepository
     */
    protected $users;

    /**
     * 创建一个新的属性composer.
     *
     * @param UserRepository $users
     * @return void
     */
    public function __construct(UserRepository $users)
    {
        // Dependencies automatically resolved by service container...
        $this->users = $users;
    }

    /**
     * 绑定数据到视图.
     *
     * @param View $view
     * @return void
     */
    public function compose(View $view)
    {
        $view->with('count', $this->users->count());
    }
}

视图被渲染前,Composer 类的 compose 方法被调用,同时 Illuminate\Contracts\View\View 被注入该方法,从而可以使用其 with 方法来绑定数据到视图。

注:所有视图 Composer 都通过服务容器被解析,所以你可以在 Composer 类的构造函数中声明任何你需要的依赖。

添加 Composer 到多个视图

你可以传递视图数组作为 composer 方法的第一个参数来一次性将视图 Composer 添加到多个视图:

view()->composer(
    ['profile', 'dashboard'],
    'App\Http\ViewComposers\MyViewComposer'
);

composer 方法接受 * 通配符,从而允许将一个 Composer 添加到所有视图:

view()->composer('*', function ($view) {
    //
});

视图创建器

视图创建器和视图 Composer 非常类似,不同之处在于前者在视图实例化之后立即失效而不是等到视图即将渲染。使用 create 方法即可注册一个视图创建器:

view()->creator('profile', 'App\Http\ViewCreators\ProfileCreator');

学院君 has written 675 articles

资深PHP工程师,Laravel学院院长

8 thoughts on “[ Laravel 5.3 文档 ] 视图 & 模板 —— 视图

    1. 1yeon万年 says:

      应该翻译有点问题,应该是 “视图创建器会在视图初始化后就立即运行,而不是像视图组件一样要一直等到视图即将被渲染完成时才会被运行”不管是creator 还是 composer 实际上是调用Factory的addViewEvent方法添加一些列的事件,而listener就是传入的闭包或者对象;看一下代码可以看到,实际上我们在view(‘test’)的时候调用了Factory的make方法,make方法调用的时候就触发了creating 事件,但是这个时候并没有触发composing事件,也就是说 视图创建器会在视图初始化后就立即运行那composing事件是在什么时候触发的呢?在Response创建的时候,$response的构造函数里面调用了setContent方法,setContent方法里面会判断content的内容,如果是json的话就设置json头,并转换成json数据,如果是可渲染的话就调用render()方法:elseif ($content instanceof Renderable) { $content = $content->render(); }而如果是视图响应的话这个时候$content就是一个IlluminateViewView实例,这个对象实现了 Renderable 接口,看看他的render方法里面:$contents = $this->renderContents(); 而renderContents方法里面调用了view工厂的callComposer 方法:$this->factory->callComposer($this);这个方法正是触发composing事件的地方。

发表评论

标记为*的字段是必填项(邮箱地址不会被公开)

你可以使用这些HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>