在 Laravel 中扩展 Blade - 创建自定义表单 object
Extending Blade in Laravel - Creating a custom form object
documentation on extending blade in Laravel 5 似乎没有太多深度,我正在努力理解我想做的事情是否可行。
注意:我正在使用 Laravel 5.1
这是 Laravel 文档给出的扩展 blade 的唯一示例。
Blade::directive('datetime', function($expression) {
return "<?php echo with{$expression}->format('m/d/Y H:i'); ?>";
});
现在我想要做的是创建一个如下所示的 blade 文件:
@form('horizontal')
{{ $form->text('email') }}
{{ $form->text('password') }}
{{ $form->submit }}
@endform
然后我希望在我使用@form 时创建一个新的$form object 并在我使用@form 之后可以使用它,但在@endform[= 之后它不需要可用19=]
经过一些谷歌搜索和闲逛后,我发现我可以做这样的事情:
\Blade::directive('form', function($expression) {
return '<?php $form = new App\Form'.$expression.'; ?>
<?php echo $form->open(); ?>';
});
(这是根据之前的编辑更新的)
这就是大部分内容。我有一个 $form object,可以创建一个新表单,我可以将自定义参数发送到该表单 object。我也可以在@form 之后使用$form object。当然它会在整个视图中可用,这并不完美,但不一定是问题。
然而,由于我似乎在做一些完全没有记录的事情,我担心我可能做错了什么,或者我可能 运行 以后会遇到问题。
我还应该注意到,我在网上找到的每一个指南都提到了 $compiler->createMatcher 和 $compiler->createPlainMatcher 但这两个似乎都在 Laravel 5.1.
中被删除了
任何人都可以深入了解 blade 扩展的工作原理并提出更好的方法吗?现在它似乎可以正常工作,但感觉非常 'hacky' 并且可能不安全地继续前进。
更新HTML宏
根据下面建议 HTML 宏的答案更新此用例。 CSS 框架 Bootstrap 包括垂直和水平形式的不同格式。此功能的目的是使两者之间的切换变得容易,示例如下:
@form('horizontal')
{{ $form->text("email", $user->email, 'Email') }}
@endform
表单 class 可能看起来像这样:
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宏无法实现这种事情。
这都是伪示例代码,对于任何错误,我们深表歉意。我相信它的基本前提应该很清楚。
您可能需要查看此插件 "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
in your service provider. See my answer here.
public function createOpenMatcher($function){
return '/(?<!\w)(\s*)@'.$function.'\(\s*(.*)\)/';
}
根据评论更新
所以根据您的评论,Illuminate 表单助手将执行您的要求。
{{ 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% 理解您的问题,但我认为您可能正在尝试使用 Blade 扩展来解决一些问题,而使用您的代码编辑器或表单助手插件可能更容易解决这些问题。也许您可以添加您尝试生成的两种类型的 HTML,我们可以讨论一下?
我都用PhPStorm and Sublime text. Both of these have options where you can include code snippets of text. In PhPStorm they are called Live Templates and Sublime calls them snippets。
我为我的文本字段使用 PhPStorm 的 textfield
tab 实时模板。
<!-- $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>
虽然我不时扩展 Blade。我发现在大多数情况下,当我想扩展它时,通常有更简单的方法。
最终编辑
你为什么不用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>
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
class 以添加您自己的自定义方法 - https://github.com/LaravelCollective/html/blob/5.0/src/FormBuilder.php
添加一个接受输入和方向的私有 wrap
方法。或者你甚至可以有单独的 wrapHorizontal
和 wrapVertical
方法。
尝试以下 link 您可能会发现它很有用。
http://laravel-recipes.com/categories/21
这里的表格是{{ ..Code goes here.. }}
的形式。在 laravel 5.1 中使用这些形式语法作为 {!! ..Code goes here.. !!}
.
documentation on extending blade in Laravel 5 似乎没有太多深度,我正在努力理解我想做的事情是否可行。
注意:我正在使用 Laravel 5.1
这是 Laravel 文档给出的扩展 blade 的唯一示例。
Blade::directive('datetime', function($expression) {
return "<?php echo with{$expression}->format('m/d/Y H:i'); ?>";
});
现在我想要做的是创建一个如下所示的 blade 文件:
@form('horizontal')
{{ $form->text('email') }}
{{ $form->text('password') }}
{{ $form->submit }}
@endform
然后我希望在我使用@form 时创建一个新的$form object 并在我使用@form 之后可以使用它,但在@endform[= 之后它不需要可用19=]
经过一些谷歌搜索和闲逛后,我发现我可以做这样的事情:
\Blade::directive('form', function($expression) {
return '<?php $form = new App\Form'.$expression.'; ?>
<?php echo $form->open(); ?>';
});
(这是根据之前的编辑更新的)
这就是大部分内容。我有一个 $form object,可以创建一个新表单,我可以将自定义参数发送到该表单 object。我也可以在@form 之后使用$form object。当然它会在整个视图中可用,这并不完美,但不一定是问题。
然而,由于我似乎在做一些完全没有记录的事情,我担心我可能做错了什么,或者我可能 运行 以后会遇到问题。
我还应该注意到,我在网上找到的每一个指南都提到了 $compiler->createMatcher 和 $compiler->createPlainMatcher 但这两个似乎都在 Laravel 5.1.
中被删除了任何人都可以深入了解 blade 扩展的工作原理并提出更好的方法吗?现在它似乎可以正常工作,但感觉非常 'hacky' 并且可能不安全地继续前进。
更新HTML宏
根据下面建议 HTML 宏的答案更新此用例。 CSS 框架 Bootstrap 包括垂直和水平形式的不同格式。此功能的目的是使两者之间的切换变得容易,示例如下:
@form('horizontal')
{{ $form->text("email", $user->email, 'Email') }}
@endform
表单 class 可能看起来像这样:
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宏无法实现这种事情。
这都是伪示例代码,对于任何错误,我们深表歉意。我相信它的基本前提应该很清楚。
您可能需要查看此插件 "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
in your service provider. See my answer here.
public function createOpenMatcher($function){
return '/(?<!\w)(\s*)@'.$function.'\(\s*(.*)\)/';
}
根据评论更新
所以根据您的评论,Illuminate 表单助手将执行您的要求。
{{ 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% 理解您的问题,但我认为您可能正在尝试使用 Blade 扩展来解决一些问题,而使用您的代码编辑器或表单助手插件可能更容易解决这些问题。也许您可以添加您尝试生成的两种类型的 HTML,我们可以讨论一下?
我都用PhPStorm and Sublime text. Both of these have options where you can include code snippets of text. In PhPStorm they are called Live Templates and Sublime calls them snippets。
我为我的文本字段使用 PhPStorm 的 textfield
tab 实时模板。
<!-- $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>
虽然我不时扩展 Blade。我发现在大多数情况下,当我想扩展它时,通常有更简单的方法。
最终编辑
你为什么不用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>
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
class 以添加您自己的自定义方法 - https://github.com/LaravelCollective/html/blob/5.0/src/FormBuilder.php
添加一个接受输入和方向的私有 wrap
方法。或者你甚至可以有单独的 wrapHorizontal
和 wrapVertical
方法。
尝试以下 link 您可能会发现它很有用。 http://laravel-recipes.com/categories/21
这里的表格是{{ ..Code goes here.. }}
的形式。在 laravel 5.1 中使用这些形式语法作为 {!! ..Code goes here.. !!}
.