2015-06-10 50 views
2

documentation on extending blade in Laravel 5似乎没有太多深度,我正努力去理解,如果我想要做什么是可能的。在Laravel中扩展刀片 - 创建自定义表单对象

注:我使用Laravel 5.1

这是Laravel文档给予延长叶片的唯一例子。

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但它并不需要是@endform

后可用一点谷歌搜索后,只是瞎搞,我发现我可以做这样的事情:

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

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

这是大多数的方式。我有一个$ form对象,并可以创建一个新的窗体,我可以发送一个自定义参数给该窗体对象。我也可以在@form之后使用$ form对象。当然,从整个观点来看,这并不完美,但不一定是问题。

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

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

任何人都可以提供有关刀片扩展如何工作的任何见解,并提出更好的方法来做到这一点?现在它似乎正常工作,但感觉非常'哈克',并且可能不安全依靠前进。

更新HTML宏

要更新一个用例此基础上下方暗示HTML宏答案。 CSS框架引导包括垂直和水平表单的不同格式。这个功能的目的是要使它容易在这两者之间进行切换,一个例子如下:那么

@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宏无法实现这种事情。

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

+0

您可以扩展FormBuilder类并相当容易地实现此功能,而无需接触Blade。看一下'Form :: model()'以及它如何保存模型的状态。您可以创建自己的开放方法,或者使用其他参数扩展现有的方法,并在稍后使用单个方法时使用它。 –

+0

@Cryode我还没有听说过Form :: model()方法,因此将研究如何工作。 – robjbrain

回答

3

你可能想看看这个插件"illuminate/html": "~5.0"

你可以做类似开放形式的东西,这两种方法都行。

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

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

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

{!! 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() !!} 

还有很多其他的,see the source

就您的原始问题而言,您始终可以使用5.0功能,并将原始方法createOpenMatcher放入您的服务提供商。根据注释

所以每次你对此有何评论See my answer here.

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

更新,在照亮形式助手将做你的要求。

{{ Form::open(['class' => 'form-horizontal']) }} 

作为

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

任何传递给数组被添加到形式标签哪个渲染。

我可能无法100%理解你的问题,但我认为你可能试图用刀片扩展来解决一些可能更容易用你的代码编辑器或Form辅助插件解决的问题。也许你可以添加你正在尝试生成的两种类型的HTML,我们可以讨论这些?

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

我使用textfield选项卡用于我的文本字段的PhPStorm实时模板。

<!-- $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> 

它给你呈现HTML

<div class="form-group"> 
     <label for="sample">Sample:</label> 
     <input class="form-control" 
       id="sample" 
       placeholder="Sample" 
       name="sample" 
       type="text"> 
</div> 

我虽然从时间延长叶片的时间。我发现大多数时候,当我想扩展它时,通常有一个更简单的方法。

最后编辑

你为什么不使用CSS?

<style> 
    form.horizontal .col-sm-10, form.horizontal .col-sm-2{ 
     display:inline-block; 
    } 
</style> 

<form class="horizontal"> 
    <div class="form-group"> 
     <label class="col-sm-2 control-label" for="field_name">Enter Name:</label> 
     <div class="col-sm-10"> 
      <input type="text" value="New Name" /> 
     </div> 
    </div> 
</form> 
<form class="vertical"> 
    <div class="form-group"> 
     <label class="col-sm-2 control-label" for="field_name">Enter Name:</label> 
     <div class="col-sm-10"> 
      <input type="text" value="New Name" /> 
     </div> 
    </div> 
</form> 
+0

请参阅我的问题的更新。对于这个特定的用例我没有任何帮助,因为我可以根据发送到Form类的__construct方法的内容修改每个方法。 – robjbrain

+0

@robjbrain我根据您的意见更新了答案。 – whoacowboy

+0

感谢您的更新,但我仍然认为它有点错过了这一点。示例HTML位于我的问题的Form类中。 – robjbrain

1

Laravel的Forms包已经被提取出核心框架。它可在这里 - http://laravelcollective.com/docs/5.0/html

恕我直言,扩展刀片不是实现你想要的最好的方式。您可以使用上面的包中的自定义宏。例如。,

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方法。

+0

嗯,我不知道这是否完全相同。用例(在这个例子中)是将Bootstrap的水平和垂直形式使用不同的标记。我会扩展我的问题来引用此。如果这可以通过宏来完成,我会留下深刻的印象,但我不认为它可以。 – robjbrain

+0

我已更新我的问题。 – robjbrain

+0

谢谢我将考虑扩展formBuilder类,并更新一次我尝试了一些东西 – robjbrain

0

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

这里的表格形式为{{ ..Code goes here.. }}。在laravel 5.1中,使用这些格式语法作为{!! ..Code goes here.. !!}