laravel 刀片,如何附加到一个部分

Posted

技术标签:

【中文标题】laravel 刀片,如何附加到一个部分【英文标题】:laravel blade, how to append to a section 【发布时间】:2014-12-24 07:09:12 【问题描述】:

如果你查看 laravel 官方文档http://laravel.com/docs/4.2/templates 它说给这个布局:

<!-- Stored in app/views/layouts/master.blade.php -->

<html>
    <body>
        @section('sidebar')
            This is the master sidebar.
        @show

        <div class="container">
            @yield('content')
        </div>
    </body>
</html>

由这个视图扩展

@extends('layouts.master')

@section('sidebar')


    <p>This is appended to the master sidebar.</p>
@stop

@section('content')
    <p>This is my body content.</p>
@stop

将附加到sidebar 部分。但实际上,如果您尝试它不会追加,它只是覆盖扩展模板中的内容。

我听说过其他刀片功能,例如 @append, @prepend, @parent... 似乎没有人工作。

此外,官方文档中的这个例子不起作用,我发现刀片文档很差。例如,没有像 @parent 这样的刀片功能。

【问题讨论】:

我同意你的观点,从成熟度的角度来看,Blade 模板引擎缺乏很多,这反映在非常缺乏文档上。我个人认为它是 Laravel 的(少数)弱点之一,幸运的是,如果你想通过插入另一个模板引擎(如 Smarty)来避免这种情况。我决定采用这种方法(在这里查看我之前的问题***.com/questions/25900826/…)。不过 Blade 用户似乎对此很满意,所以也许有人会调查您的问题。 @jbx 使用另一个模板引擎,我认为这是个好主意。我认为 symfony 框架中流行的 Twig 似乎是 laravel 项目的一个不错的选择,即使它更难学习。 Twig 也比 Blade 好,因为你几乎可以在任何 php 项目中使用它,而不仅仅是绑定到 laravel。对于 smarty,我只是觉得它的官方 smarty.net 网站太可怕了。 如果你为 Twig 找到了一个好的 Laravel 提供程序,那么你可以根据需要使用它。我只是更喜欢 Smarty,因为我对它有很多经验,而且我更喜欢 Twig 的语法(我讨厌双卷曲 以及与 % 的不一致等),但它绝对比 Blade 更成熟。我发现 Smarty 的文档非常全面(与 Blade 相比,它是一个完全不同的联盟)。所有功能都有完整的解释和示例。也许该网站有点过时(我认为它是最古老的 PHP 模板引擎之一),但它拥有一切。 【参考方案1】:

documentation from Laravel website中的例子确实似乎有缺陷,但我认为是网站上的markdown解析问题,same docs on github显示正确代码:

无论如何@parent 确实有效。文档中的示例应如下所示:

@extends('layouts.master')

@section('sidebar')
    @parent

    <p>This is appended to the master sidebar.</p>
@stop

@section('content')
    <p>This is my body content.</p>
@stop

快速查看Illuminate/View/Factory.php 可以确认@parent 的作用:

/**
 * Append content to a given section.
 *
 * @param  string  $section
 * @param  string  $content
 * @return void
 */
protected function extendSection($section, $content)

    if (isset($this->sections[$section]))
    
        $content = str_replace('@parent', $content, $this->sections[$section]);
    

    $this->sections[$section] = $content;

【讨论】:

这就是为什么我说 Laravel 的文档总体上仍然很差,不仅仅是刀片组件。您会发现自己潜入源代码以了解如何使用函数!不是每个人都愿意这样做。甚至源代码里面的 cmets 也非常简洁。你必须是 Laravel 的专家才能理解它们。 @Amaynut 我认为这是一个观点问题。我同意那里的文档中缺少某些内容,但我不会说它很差。深入研究源代码也不是那么痛苦,事实上我认为这是一件好事,每个致力于学习新工具的开发人员都应该尽可能地了解它是如何工作的(没有人会期望成为从一开始就是专家,但有一定编码经验的人根本不会觉得这令人生畏)。 @Bogdan 这是一个非常歪曲的观点,根本不是“好事”。当你提供一个框架时,你永远不应该把它扔在那里,并期望人们阅读代码才能使用它。它破坏了封装、重用和基本软件工程原则的全部意义。显然这是开源的,而且它是免费的且不附加任何条件的事实降低了作者期望的承诺水平(如果我没记错的话,目前仍然是一个主要人物)。但这并不会突然变得“好”,有据可查的 API 仍然比无证的更好。 @jbx 我想你误会了。我并不是说拥有良好的文档并不重要。我只是在指出开源的魔力,如果你想了解一些东西的内部运作,你可以,但你不能说那是“根本不是‘好东西’” @Bogdan,是的,当然,我绝不想贬低这个人在 Laravel 上所做的工作。我认为它很棒。但是,我不同意某些人的观点,即您只是将一些东西扔在那里并期望人们从中理解。代码可能有数千行,而对描述函数行为方式的几行的简单描述就足以让用户继续使用它。除了可能存在错误之外,还会出现预期的记录行为与实际实现之间的不匹配,这使人们能够识别并修复它。【参考方案2】:

您可以简单地使用@append...

@extends('layouts.master')

@section('sidebar')
    <p>This is appended to the master sidebar.</p>
@append

@section('content')
    <p>This is my body content.</p>
@stop

See here.

要了解其工作原理...

BladeCompiler 中的compileStatements() 方法调用了compileAppend() 方法,您可以在此处看到:

/**
 * Compile Blade Statements that start with "@"
 *
 * @param  string  $value
 * @return mixed
 */
protected function compileStatements($value)

    $callback = function($match)
    
        if (method_exists($this, $method = 'compile'.ucfirst($match[1])))
        
            $match[0] = $this->$method(array_get($match, 3));
        

        return isset($match[3]) ? $match[0] : $match[0].$match[2];
    ;

    return preg_replace_callback('/\B@(\w+)([ \t]*)(\( ( (?>[^()]+) | (?3) )* \))?/x', $callback, $value);

反过来,这会插入对appendSection() 的调用,如下所示:

/**
 * Stop injecting content into a section and append it.
 *
 * @return string
 */
public function appendSection()

    $last = array_pop($this->sectionStack);

    if (isset($this->sections[$last]))
    
        $this->sections[$last] .= ob_get_clean();
    
    else
    
        $this->sections[$last] = ob_get_clean();
    

    return $last;

【讨论】:

它不起作用,追加只会覆盖父部分。为什么在发布之前不尝试解决方案? 它确实有效,我目前在我的几个项目中使用它。它是在 Laravel 4.1 中添加的,正如 Taylor 所说的 here 并且仍然在 Laravel 5 的 dev 分支中工作。它也适用于 this thread 中的 OP。 抱歉,我有最新的 Lavarel 稳定版本 4.2,我测试过但它不起作用。只有 @parent 方法对我有用。如果省略@parent,无论你使用哪种方法@stop@show@endsection都会覆盖,@append...即使在您在评论中提到的线程中,他们也提到了这一点:“NVM,知道了 - 需要'@parent'” 如果您查看时间戳,该评论是在我的评论之前发表的。然后他将我的标记为答案。我可以向你保证它有效,并且在发布之前我确实对其进行了测试。 它在 4.2 中有效,但有细微的变化。第一部分应以“@stop”或“@show”结尾,后续部分应以“@append”结尾。【参考方案3】:

如前所述,我使用了@parent,它对我来说很好用。可能是扩展 title 的一个示例,将有所帮助:

ma​​ster.blade.php

@section('title')
My Blog 
@stop
<!doctype html>
<html>
<head>
    @include('includes.head')
</head>
<body>
<div class="container-fluid">
    <div id="main" class="row">
            @yield('content')
    </div>
</div>
</body>
</html>

包括/head.blade.php

<meta charset="utf-8">
<title>@yield('title')</title>

post.blade.php

@extends('master')

@section('title')
@parent
| $post->title 
@stop
@section('content')
// Post Body here ..
@stop

因此,Title 会被渲染成这样:

我的博客 |我的帖子标题


实际上,这将呈现如下内容:

<title>
    My Blog
    | My Post Title
</title> 

所以你可以使用 section 第二个参数来设置值:

包括/head.blade.php

...
@section('title', 'My Blog')
...

post.blade.php

...
@section('title', '@parent | ' . $post->ar_name )
...

这将呈现:

<title>My Blog | My Post Title</title> 

这样你就可以去掉标题内的线条了,

希望对您有所帮助。

注意: 这用于 Laravel 5.2,不太确定,但我记得,它也适用于 Laravel 4。

【讨论】:

以上是关于laravel 刀片,如何附加到一个部分的主要内容,如果未能解决你的问题,请参考以下文章

使用javascript将具有删除操作的表单附加到laravel刀片文件

Laravel 刀片上的 Vuejs

laravel在数据库中的刀片页面中附加html代码[重复]

如何使用 javascript/jquery 将大型 html 块附加到刀片文件?

laravel:如何包含刀片布局中的部分?

Laravel - 刀片注释,刀片渲染导致页面崩溃