如何在Laravel Blade模板中设置变量

344
我正在阅读 Laravel Blade 文档,但我无法弄清楚如何在模板中分配变量以供稍后使用。我不能使用 {{ $old_section = "whatever" }},因为它会输出“whatever”,而我不想要那样。
我知道可以使用 <?php $old_section = "whatever"; ?>,但那不够优雅。
在 Blade 模板中是否有更好、更优雅的方法来处理这个问题?

1
请查看此拉取请求:https://github.com/laravel/laravel/pull/866 - Spir
这在测试时通常很有用,尤其是如果你正在处理模板而其他人正在处理PHP部分。只需确保在测试完成后删除声明即可。 - trysis
1
仅仅使用<?php $old_section = "whatever"; ?>有什么问题?我觉得它非常易读。 - Jaime Hablutzel
2
在我看来,@JaimeHablutzel,答案就在问题中:它不够优雅。 - duality_
1
@duality_ 使用黑客总是不够优雅的,如果想使用黑客,请不要寻求优雅。 - Silidrone
31个回答

490

简单方法

如果您想定义多个变量,请使用 Blade 指令的完整形式:

@php
   $i = 1;
   $j = 2;
@endphp
如果您只想定义一个变量,也可以使用单个PHP语句:
@php($i = 1)

更高级:添加一个“DEFINE”标签

如果您想使用自定义标签并使用@define而不是@php,请像这样扩展Blade:

/*
|--------------------------------------------------------------------------
| Extend blade so we can define a variable
| <code>
| @define $variable = "whatever"
| </code>
|--------------------------------------------------------------------------
*/

\Blade::extend(function($value) {
    return preg_replace('/\@define(.+)/', '<?php ${1}; ?>', $value);
});

然后执行以下操作之一:

快速解决方案:如果您懒得动手,只需将代码放在 AppServiceProvider.php 的 boot() 函数中即可。

更好的解决方案: 创建自己的服务提供程序。请参见https://dev59.com/9WMl5IYBdhLWcg3wiXV7#28641054以了解如何在 Laravel 5 中扩展 Blade。这种方法需要更多的工作,但是它是使用提供程序的好练习 :)

完成上述更改后,您可以使用:

@define $i = 1

定义一个变量。


7
好的!请注意,您可以使用您的实现来执行任何PHP语句。我会将它重命名为类似@php这样的东西。非常方便... - igaster
非常正确,igaster。如果你想的话,你可以将“define”重命名为“php”,但这会导致在模板中过度使用PHP的陷阱 :) - Pim
1
感谢@C.delaFonteijne,如果您正在使用命名空间(而且您应该这样做),则确实需要\。我已经在上面的代码中添加了\。 - Pim
1
请注意,自Laravel 5.2以来,几乎您的完整实现已成为标准(https://github.com/illuminate/view/blob/5.2/Compilers/BladeCompiler.php#L797-L819)。 您可以使用@php(@i = 1)或在块语句中使用它(使用@endphp关闭)。 - Daan
2
我不明白"@php" "@endphp"怎么比"<?php" "?>"更"优雅"。它甚至多了几个字符!难道只是因为它像其他Blade指令一样以"@"开头吗?我们开发人员真是一群强迫症患者!;-) - OMA
显示剩余5条评论

137

在视图中这样做是不鼓励的,因此没有相应的Blade标签。 如果确实想要在Blade视图中这样做,可以直接像您编写的那样打开PHP标记,或者注册一个新的Blade标签。以下是示例:

<?php
/**
 * <code>
 * {? $old_section = "whatever" ?}
 * </code>
 */
Blade::extend(function($value) {
    return preg_replace('/\{\?(.+)\?\}/', '<?php ${1} ?>', $value);
});

11
视图中的变量有一些用途。这很好!把这段代码放在哪个位置比较好? - duality_
1
你可以将它放在你的应用程序/start.php中,或者如果你有更多类似的东西,可以将它放在一个单独的文件中并在那里包含它。Laravel在这方面非常灵活,你甚至可以将它放在控制器中。唯一需要做的是在视图渲染之前进行扩展。 - TLGreg
22
为什么要添加这个额外的代码才能使用{?,而不能直接使用原生的<? - Justin
1
如果这样做不被鼓励,那么有没有更“合适”的方法来完成以下操作?我有一个网站,在主应用程序视图中呈现标题为{{ $title }},其中包含一个子系统,需要将页面编号附加到标题上(“申请表第{{ $page }}页”),并且我正在将$page传递给视图(在视图内部其他地方也使用)。我不想在每个控制器调用中构建标题,我只想发送视图页面编号-以防有一天我想更改基本标题。我现在使用<?php $title = ... ?>,但是否有更正确的方法? - jdavidbakr
5
变量应该从控制器传递,而不是在视图中内联声明。如果全局模板需要一个变量,可以在服务提供者中设置它https://dev59.com/dGcs5IYBdhLWcg3wRBtQ#36780419。如果页面特定的模板需要一个变量,请使用@yield并从具有控制器的子视图传递它。https://laravel.com/docs/5.1/blade#template-inheritance - Justin
显示剩余3条评论

119
中,您可以使用模板注释语法来定义/设置变量。
注释语法是{{-- 这里可以是任何注释 --}},由引擎呈现为 <?php /* 这里可以是任何注释 */ ?> 因此,我们可以通过一些技巧使用它来定义变量,例如:
{{-- */$i=0;/* --}}

将由呈现为<?php /* */$i=0;/* */ ?>,这会为我们设置变量,而不更改任何代码行。


3
不是“最佳实践”的方式,但对于在模板中快速进行代码黑客攻击非常完美,就像使用html中的“内联样式”一样。 - Markus Hofmann
137
我不建议你使用这个黑客技巧,因为任何在你之后查看这段代码的人都会讨厌你。 - Justin
2
同意Justin的观点,注释标记是用来进行注释的,将其取消注释并开始执行其他操作会带来麻烦。 - Leon
28
这并不比普通的 PHP <?php $i=0; ?> 更好。 - gyo
3
与使用PHP标签相比,这样做有什么好处?它不易读(看起来像注释),需要更多的打字,而且可能在解析系统更新时出现错误。即使有一定用处,也不是如何在Blade模板中定义变量的答案。我不知道选民们有什么问题,也许他们觉得这太“极客”了?嗯... - DarkWingDuck
显示剩余3条评论

62

有一个简单的解决方法,不需要更改任何代码,在 Laravel 4 中同样适用。

你可以在传递给 @if 语句的表达式中使用赋值运算符 (=),而不是(例如)== 等运算符。

@if ($variable = 'any data, be it string, variable or OOP') @endif

然后您可以在任何可以使用其他任何变量的地方使用它

{{ $variable }}

唯一的缺点是如果有人不知道你这样做是为了解决问题,那么你的任务看起来就像是一个错误。


39

你们把它搞得太复杂了。

只需使用原始的PHP。

<?php $i = 1; ?>
{{$i}}

donesies.

(或者https://github.com/alexdover/blade-set看起来也很简单)

我们都有点像在“黑客攻击”系统,通过在视图中设置变量,那么为什么要让这个“黑客攻击”比必要的更加复杂呢?

在 Laravel 4 中进行了测试。

另一个好处是语法高亮可以正常工作(我之前使用评论黑客技巧,但阅读起来太糟糕了)


28

自Laravel 5.2.23版本以来,您可以使用@php Blade指令,您可以将其用于内联或块语句中:

@php($old_section = "whatever")
或者
@php
    $old_section = "whatever"
@endphp

23

您可以通过以下方式在Blade模板引擎中设置变量:

1. 通用PHP块
设置变量:<?php $hello = "Hello World!"; ?>
输出:{{$hello}}

2. Blade PHP块
设置变量:@php $hello = "Hello World!"; @endphp
输出:{{$hello}}


20

您可以在视图文件中设置一个变量,但它会按照您设置的方式进行打印。无论如何,有一个解决方法。您可以将变量设置在未使用的部分内。例如:

@section('someSection')
  {{ $yourVar = 'Your value' }}
@endsection

那么{{ $yourVar }}将在你想要的任何地方打印Your value,但是当你保存变量时,你不会得到输出。

编辑:必须命名该部分,否则将抛出异常。


无法工作,需要包含其他内容 未定义的属性:Illuminate\View\Factory::$startSection(视图:/home/vagrant/Code/dompetspy/resources/views/reviews/index.blade.php) - MaXi32
其实这非常聪明!只需将您的部分称为“variables”,并严格在刀片中用于分配变量,就可以完成了! - Lamar

19

为什么要添加已经存在的答案呢? - Sergey Nevmerzhitsky

17

在 Laravel 4 中:

如果您希望该变量在所有视图中都可以访问,而不仅仅是模板中,请使用View::share方法(此博客有更多信息)。

只需在 app/controllers/BaseController.php 中添加以下代码:

class BaseController extends Controller
{
  public function __construct()
  {                   
    // Share a var with all views
    View::share('myvar', 'some value');
  }
}

现在,$myvar 将会对你的所有视图(包括模板)可用。

我使用了这个来为我的图片设置特定于环境的资源URL。


1
这正是我一直在寻找的:避免在数据库中重复调用的好方法! - clod986
在Laravel 5中似乎没有这个选项? - Goddard
@Goddard 你仍然可以。不过语法已经改变了:https://dev59.com/dGcs5IYBdhLWcg3wRBtQ#36780419 - Justin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接