Laravel视图入门 ( Getting Started With Laravel Views )
Views hold the presentation logic of a Laravel application. It is served separately from the application logic using laravel's blade templating engine.
视图具有Laravel应用程序的表示逻辑。 它使用laravel的刀片模板引擎与应用程序逻辑分开提供。
Passing data from a controller to a view is as simple as declaring a variable and adding it as a parameter to the returned view helper method. There is no shortage of ways to do this.
将数据从控制器传递到视图就像声明变量并将其作为参数添加到返回的视图帮助器方法一样简单。 不乏方法。
We will create a SampleController
class that will handle our logic
我们将创建一个SampleController
类来处理我们的逻辑
php artisan make:controller SampleController
Here is a sample controller in app/Http/Controllers/SampleController.php
这是app/Http/Controllers/SampleController.php
的示例控制器
class SampleController extends Controller
{
/**
* pass an array to the 'foo' view
* as a second parameter.
*/
public function foo()
{
return view('foo', [
'key' => 'The big brown fox jumped over the lazy dog'
]);
}
/**
* Pass a key variable to the 'foo view
* using the compact method as
* the second parameter.
*/
public function bar()
{
$key = 'If a would chuck can chuck wood,';
return view('foo', compact('key'));
}
/**
* Pass a key, value pair to the view
* using the with method.
*/
public function baz()
{
return view('foo')->with(
'key',
'How much woood would a woodchuck chuck.'
);
}
}
将数据传递到多个视图 ( Passing Data To Multiple Views )
This is all fine and dandy. Well it is until you try passing data to many views.
这一切都很好,花花公子。 好吧,直到您尝试将数据传递到许多视图为止。
More often than not, we need to get some data on different pages. One such scenario would be information on the navigation bar or footer that we be available across all pages on your website, say, the most recent movie in theatres.
通常,我们需要在不同页面上获取一些数据。 一种这样的情况是导航栏或页脚上的信息,我们可以在您网站的所有页面上找到这些信息,例如剧院中的最新电影。
For this example, we will use an array of 5 movies to display the latest movie (the last item on the array) on the navigation bar.
对于此示例,我们将使用5个电影的数组在导航栏上显示最新的电影(数组中的最后一项)。
For this, I will use a boostrap template to setup the navigation bar in resources/views/app.blade.php
.
为此,我将使用boostrap模板在resources/views/app.blade.php
设置导航栏。
<nav class="navbar navbar-inverse">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">Movie Maniac</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li><a href="foo">Foo</a></li>
<li><a href="bar">Bar</a></li>
<li><a href="baz">Baz</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li><a href="#">latest movie title here</a></li>
</ul>
</div>
<!-- /.navbar-collapse -->
</div>
<!-- /.container-fluid -->
</nav>

The latest movie text on the far right will however be replaced with a title from our movie list to be created later on.
但是,最右边的最新电影文本将替换为电影列表中的标题,以便稍后创建。
Let's go ahead and create our movie list on the homepage.
让我们继续在主页上创建电影列表。
路线 (Routes)
View all the routes in app/Http/routes.php
查看app/Http/routes.php
所有路由
Route::get('/', 'SampleController@index');
Route::get('/foo', 'SampleController@foo');
Route::get('/bar', 'SampleController@bar');
Route::get('/baz', 'SampleController@baz');
We are just creating four simple routes.
我们只是在创建四个简单的路线。
控制者 (Controller)
View the controller in app/Http/Controllers/SampleController.php
在app/Http/Controllers/SampleController.php
查看控制器
/**
* Return a list of the latest movies to the
* homepage
*
* @return View
*/
public function index()
{
$movieList = [
'Shawshank redemption',
'Forrest Gump',
'The Matrix',
'Pirates of the Carribean',
'Back to the future',
];
return view('welcome', compact('movieList'));
}
视图 (View)
See latest movie views in resources/views/welcome.blade.php
在resources/views/welcome.blade.php
查看最新的电影观看
@extends('app')
@section('content')<h1>Latest Movies</h1>
<ul>
@foreach($movieList as $movie)
<li class="list-group-item"><h5>{{ $movie }}</h5></li>
@endforeach
</ul>
@endsection
It goes without saying that my idea of latest movies is skewed, but we can overlook that for now. Here is what our homepage looks like now.
毋庸置疑,我对最新电影的想法是歪曲的,但现在我们可以忽略它。 这是我们主页现在的样子。

Awesome! We have our movie list. And now to the business of the day.
太棒了! 我们有电影清单。 如今已成为当今的业务。
更新索引控制器方法 ( Update Index Controller Method )
We will assume that Back to the future, being the last movie on our movie list, is the latest movie, and display it as such on the navigation bar.
我们将假设Back to the future (电影列表中的最后一部电影)是最新的电影,并在导航栏上将其显示为最新电影。
/**
* Return a list of the latest movies to the
* homepage
*
* @return View
*/
public function index()
{
$movieList = [
'Shawshank redemption',
'Forrest Gump',
'The Matrix',
'Pirates of the Carribean',
'Back to the future',
];
$latestMovie = end($movieList);
return view('welcome', compact('movieList', 'latestMovie'));
}
共享视图文件中的错误 ( Error In Shared View File )
We now have Back to the future as our latest movie, and rightfully so because Back to the Future 4 was released a week from now in 1985. I cannot make this stuff up.
现在,我们拥有《 回到未来》作为我们的最新电影,这是正确的,因为《 回到未来》 4是从1985年开始的一周后发行的。我无法弥补这一点。

This seems to work. Well until you try navigating to other pages (Try one of foo, bar, baz) created earlier on. This will throw an error.
这似乎有效。 好吧,直到您尝试导航到之前创建的其他页面(尝试foo,bar,baz之一)。 这将引发错误。

修复共享视图中的错误 ( Fixing Error in Shared View )
This was expected and by now you must have figured out why this happened. We declared the latest movie variable on the index
method of the controller and passed it to the welcome
biew. By extension, we made latestMovie
available to the navigation bar BUT only to views/welcome.blade.php
.
这是预料之中的,现在您必须已经弄清楚了为什么会发生这种情况。 我们在控制器的index
方法上声明了最新的movie变量,并将其传递给了welcome
biew。 通过扩展,我们使latestMovie
仅可用于views/welcome.blade.php
但可用于导航栏。
When we navigate to /foo
, our navigation bar still expects a latestMovie
variable to be passed to it from the foo
method but we have none to give.
当我们导航到/foo
,导航栏仍然期望从foo
方法传递一个latestMovie
变量给我们,但是我们没有任何变量。
There are three ways to fix this
有三种方法可以解决此问题
Declare the
latestMovie
value in every other method, and in this case, themovieList
too. It goes without saying we will not be doing this.在其他所有方法中声明
latestMovie
值,在这种情况下,movieList
。 不用说我们不会这样做。Place the movie information in a service provider's boot method. You can place it on
App/Providers/AppServiceProvider
or create one. This quickly becomes inefficient if we are sharing alot of data.将影片信息放入服务提供商的启动方法中 。 您可以将其放在
App/Providers/AppServiceProvider
或创建一个。 如果我们共享大量数据,这很快就会变得效率低下。
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
view()->share('key', 'value');
}
- Take advantage of Laravel View composers 利用Laravel View作曲家
输入左:Laravel View作曲家 ( Enter Left: Laravel View Composers )
View composers are callbacks or class methods that are called when a view is rendered. If you have data that you want to be bound to a view each time that view is rendered, a view composer can help you organize that logic into a single location.
视图编写器是呈现视图时调用的回调或类方法。 如果您有想要在每次渲染视图时将其绑定到视图的数据,则视图编辑器可以帮助您将该逻辑组织到一个位置。
-Laravel documentation
-Laravel文档
While it is possible to get the data in every controller method and pass it to the single view, this approach may be undesirable.
尽管可以通过每种控制器方法获取数据并将其传递给单个视图,但是这种方法可能是不可取的。
View composers, as described from the laravel documentation, bind data to a view every time it is rendered. They clean our code by getting fetching data once and passing it to the view.
如laravel文档中所述,视图编写器在每次呈现时都将数据绑定到视图。 他们通过一次获取数据并将其传递给视图来清理代码。
创建一个新的服务提供商 ( Creating A New Service Provider )
Since Laravel does not include a ViewComposers
directory in it's application structure, we will have to create our own for better organization. Go ahead and create App\Http\ViewComposers
由于Laravel在其应用程序结构中未包含ViewComposers
目录,因此我们将必须创建自己的目录以更好地进行组织。 继续创建App\Http\ViewComposers
We will then proceed to create a new service provider to handle all our view composers using the artisan command
然后,我们将继续创建新的服务提供者,以使用artisan command
处理所有视图撰写者
php artisan make:provider ComposerServiceProvider
The service provider will be visible in app/Providers
服务提供商将显示在app/Providers
Add the ComposerServiceProvider
class to config/app.php
array for providers
so that laravel is able to identify it.
将ComposerServiceProvider
类添加到providers
config/app.php
数组中,以便laravel能够识别它。
Modify the boot
method in the new Provider by adding a composer
method that extends view()
通过添加扩展view()
的composer
方法,在新Provider中修改boot
方法。
/**
* Bootstrap the application services.
*
* @return void
*/
public function boot()
{
view()->composer(
'app',
'App\Http\ViewComposers\MovieComposer'
);
}
Laravel will execute a MovieComposer@compose
method every time app.blade.php
is rendered. This means that every time our navigation bar is loaded, we will be ready to serve it with the latest movie from our view composer.
Laravel将执行一个MovieComposer@compose
方法每次 app.blade.php
呈现。 这意味着每次加载导航栏时,我们都准备将其与视图编辑器中的最新电影一起提供。
While MovieComposer@compose
is the default method to be called, you can overwrite it by specifying your own custom method name in the boot method.
虽然MovieComposer@compose
是要调用的默认方法,但是您可以通过在启动方法中指定自己的自定义方法名称来覆盖它。
view()->composer('app', 'App\Http\ViewComposers\MovieComposer@foobar');
创建MovieComposer ( Creating MovieComposer )
Next, we will create our MovieComposer
class
接下来,我们将创建MovieComposer
类
<?php
namespace App\Http\ViewComposers;
use Illuminate\View\View;
class MovieComposer
{
public $movieList = [];
/**
* Create a movie composer.
*
* @return void
*/
public function __construct()
{
$this->movieList = [
'Shawshank redemption',
'Forrest Gump',
'The Matrix',
'Pirates of the Carribean',
'Back to the future',
];
}
/**
* Bind data to the view.
*
* @param View $view
* @return void
*/
public function compose(View $view)
{
$view->with('latestMovie', end($this->movieList));
}
}
The with
method will bind the latestMovies to the app
view when it is rendered. Notice the we added Illuminate\View\View
.
呈现时, with
方法会将latestMovies绑定到app
视图。 注意,我们添加了Illuminate\View\View
。
使用MovieComposer清理控制器 ( Cleaning Up The Controller with MovieComposer )
We can now get rid of the latestMovie
variable and actually remove it from the compact
helper method in SampleController@index
.
现在,我们可以摆脱latestMovie
变量,并实际上从SampleController@index
的compact
帮助器方法中将其删除。
public function index()
{
$movieList = [
'Shawshank redemption',
'Forrest Gump',
'The Matrix',
'Pirates of the Carribean',
'Back to the future',
];
return view('welcome', compact('movieList'));
}
We can now access the latest movie on the navigation bar in all our routes.
现在,我们可以在所有路线的导航栏中访问最新的电影。

使用存储库优化代码 ( Optimizing Our Code With A Repository )
While we seem to have solved one issue, we seem to have created another. we now have two movieList
arrays. one in the controller and one in the constructor method in MovieComposer
.
虽然我们似乎已经解决了一个问题,但我们似乎创造了另一个问题。 我们现在有两个movieList
数组。 在MovieComposer
,一个在控制器中,一个在构造函数中。
While this may have been caused by using an array as a simple data source, it may be a good idea to fix it, say, by creating a movie repository. Ideally, the latestMovie
value would be gotten from a database using Eloquent.
尽管这可能是由于使用数组作为简单的数据源而引起的,但最好通过创建电影资料库来修复它,这是一个好主意。 理想情况下, latestMovie
值将使用数据库中得到雄辩 。
Check out the github repo for this tutorial to see how I created a Movie Repository to get around the redudancy as shown below in MovieComposer
and SampleController
.
查阅本教程的github存储库,以了解如何创建Movie Repository来避免重复,如下MovieComposer
和SampleController
。
public $movieList = [];
/**
* Create a movie composer.
*
* @param MovieRepository $movie
*
* @return void
*/
public function __construct(MovieRepository $movies)
{
$this->movieList = $movies->getMovieList();
}
/**
* Bind data to the view.
*
* @param View $view
* @return void
*/
public function compose(View $view)
{
$view->with('latestMovie', end($this->movieList));
}
public function index(MovieRepository $movies)
{
$movieList = $movies->getMovieList();
return view('welcome', compact('movieList'));
}
结论 ( Conclusion )
It is possible to create a view composer that is executed when all views are rendered by replacing the view name with an asterisk wildcard
通过用星号通配符替换视图名称,可以创建在渲染所有视图时执行的视图编辑器
view()->composer('*', function (View $view) {
//logic goes here
});
Notice that instead of passing a string with the path to MovieComposer, you can also pass a closure.
注意,除了传递带有MovieComposer路径的字符串之外,还可以传递闭包。
You can as also limit the view composer to a finite number of views, say, nav
and footer
您还可以将视图编辑器限制为有限数量的视图,例如nav
和footer
view()->composer(
['nav', 'footer'],
'App\Http\ViewComposers\MovieComposer'
);
翻译自: https://scotch.io/tutorials/sharing-data-between-views-using-laravel-view-composers