在Laravel中扩展刀片 - 创建自定义表单对象

时间:2015-06-10 15:08:56

标签: laravel laravel-5 blade

documentation on extending blade in Laravel 5似乎没有多大的深度,我很难理解我是否有可能做到这一点。

注意:我使用的是Laravel 5.1

这是Laravel Docs用于扩展刀片的唯一示例。

Blade::directive('datetime', function($expression) {
    return "<?php echo with{$expression}->format('m/d/Y H:i'); ?>";
});

现在我要做的是拥有一个如下所示的刀片文件:

@form('horizontal')
    {{ $form->text('email') }}
    {{ $form->text('password') }}
    {{ $form->submit }}
@endform

然后我希望每当我使用@form时都要创建一个新的$ form对象,并且在我使用@form后可以使用它但在@endform之后它不需要可用

经过一段谷歌搜索后,我发现我可以做到这样的事情:

\Blade::directive('form', function($expression) {
    return '<?php $form = new App\Form'.$expression.'; ?>
    <?php echo $form->open(); ?>';
});

(这是从之前的编辑更新的)

那是大部分路。我有一个$ form对象,可以创建一个新表单,我可以向该表单对象发送一个自定义参数。我也可以在@form之后使用$ form对象。当然,它将在整个视图中可用,但并不完美,但不一定是问题。

然而,由于我似乎在做一些完全没有记录的事情,我担心我可能做错了什么,或者我以后会遇到问题。

我还应该注意,我在网上找到的每一个指南都引用了$ compiler-&gt; createMatcher和$ compiler-&gt; createPlainMatcher,但这两个似乎都在Laravel 5.1中被删除了。

任何人都可以提供有关刀片扩展如何工作的任何信息,并建议更好的方法吗?现在它似乎只是工作,但感觉非常&#39; hacky&#39;并且可能不安全地依靠前进。

更新HTML MACROS

根据以下建议HTML宏的答案更新用例。 CSS Framework Bootstrap包括垂直和水平表单的不同格式。此功能的目的是使这两者之间的切换变得容易,下面是一个例子:

@form('horizontal')
    {{ $form->text("email", $user->email, 'Email') }}
@endform

Form类可能看起来像这样:

class Form
{
    public $direction;

    public function __construct($direction)
    {
        $this->direction = $direction;
    }

    public function text($name, $value, $label)
    {
        return $this->wrap('<input type="text" value="'.$value.'" />', $name, $label);
    }

    public function wrap($element, $name, $label)
    {
        if($this->direction == 'horizontal') {
            //Horizontal
            return '<div class="form-group">
                <label class="col-sm-2 control-label" for="'.$name.'">'.$label.'</label>
                <div class="col-sm-10">
                    '.$element.'
                </div>
            </div>';
        } else {
            //Vertical
            return '<div class="form-group">
                <label for="'.$name.'">'.$label.'</label>
                '.$element.'
            </div>';
        }
    }
}

据我所知,HTML Macro无法实现此类目标。

这是所有伪示例代码,因此对任何错误道歉。我相信它的基本前提应该是清楚的。

3 个答案:

答案 0 :(得分:3)

您可能希望查看此插件"illuminate/html": "~5.0"

您可以执行这两种方法可以执行的打开表单等操作。

xargs

作为奖励,您还可以获得许多其他物品。

git show --stat

还有很多人,see the source

就原始问题而言,您始终可以使用5.0功能,只需将原始方法createOpenMatcher放入服务提供商即可。 See my answer here.

{!! Form::open() !!}

{!! Form::model($pose,['method' => 'PATCH', 'route' => ['poses.update', $pose->id]]) !!}

每条评论更新

因此,根据您的评论,Illuminate表单助手将按照您的要求进行操作。

{!! Form::text('title', null, [
           'class' => 'form-control', 
           'id' => 'title', 'placeholder' => 'Add title.'
          ]) !!}
{!! Form::textarea('body', null, [
           'class' => 'form-control', 
           'id' => 'body', 'placeholder' => 'Post a status'
          ]) !!}
{!! Form::close() !!}

呈现为

public function createOpenMatcher($function){
    return '/(?<!\w)(\s*)@'.$function.'\(\s*(.*)\)/';
}

传递给数组的任何内容都会添加到表单标记中。

我可能不会100%理解您的问题,但我认为您可能正在尝试使用Blade扩展来解决使用代码编辑器或Form帮助程序插件更容易解决的问题。也许你可以添加你想要生成的两种类型的HTML,我们可以讨论一下吗?

我同时使用PhPStormSublime text。这两个都有选项,您可以在其中包含文本的代码片段。在PhPStorm中,他们被称为Live Templates,而Sublime称他们为snippets

我为我的文本字段使用了{{ Form::open(['class' => 'form-horizontal']) }} 标签实时模板PhPStorm。

<form method="POST" 
    action="http://example.com/sample" 
    accept-charset="UTF-8" 
    class="form-horizontal">
<input name="_token" 
    type="hidden" 
    value="ZqVwyZXXkh6sHLKpDJjvAJP0s6Bg5bXeuA1RcOnK">

它为您提供了渲染html

textfield

虽然我不时扩展Blade。我发现,在大多数情况下,当我想扩展它时,通常会有一种更简单的方法。

最终修改

为什么不使用CSS?

<!-- $VALUE$ Field -->
<div class="form-group">
    {!! Form::label('$NAME$', '$VALUE$:') !!}
    {!! Form::text('$NAME$', null, [
               'class' => 'form-control', 
               'id'=>'$NAME$', 
               'placeholder' => '$VALUE$'
     ]) !!}
    {!! $errors->first('$NAME$', '<span class="error">:message</span>') !!}
</div>

答案 1 :(得分:1)

Laravel有一个从核心框架中提取出来的Forms包。它可以在这里找到 - http://laravelcollective.com/docs/5.0/html

恕我直言,扩展Blade并不是达到你想要的最佳方式。您可以使用上面的包中的自定义宏。如,

Form::macro('horizontal', function()
{
    $form = '<input type="text" name="email">';
    $form .= '<input type="password" name="password">';
    $form .= '<input type="submit" value="Submit">';
    return $form;
});

在您看来:{!! Form::horizontal() !!}

修改:对以下更新问题的回复

您可以扩展FormBuilder类以添加自己的自定义方法 - https://github.com/LaravelCollective/html/blob/5.0/src/FormBuilder.php

添加一个获取输入和方向的私有wrap方法。或者您甚至可以使用单独的wrapHorizontalwrapVertical方法。

答案 2 :(得分:0)

尝试以下链接,您会发现它很有用。 http://laravel-recipes.com/categories/21

此处表格的格式为{{ ..Code goes here.. }}。在laravel 5.1中,将这些表单语法用作{!! ..Code goes here.. !!}