Laravel教程 六:表单 Forms

JellyBool

JellyBool

laravel 5.2 之后请使用 laravelcollective/html 替换 illuminate/html. 出现问题先看评论。

在开始之前,我们把界面先美化一点点先:

首先到https://github.com/JellyBool/blog-css-js得到静态文件,然后分别修改下面三个文件:

1. app.blade.php

2. articles/index.blade.php

3. articles/show.blade.php

下面的视图代码的修改部分,如果你偷懒,你可以使用ctrl+c大法。

app.blade.php中:将原来@yield('content')的代码替换成下面的代码:

<body>

    <div class="container">

            <section class="content">

                <div class="pad group">

                    @yield('content')

                </div>

            </section>

        </div>

</body>

就是在外面多加了个div和一个section。

再引入这两个css文件:

<link rel='stylesheet' href="/css/bootstrap.min.css" type='text/css' media='all'/>

<link rel='stylesheet' href="/css/all.css" type='text/css' media='all'/>

一个是bootstrap,一个是自定义的。

articles/index.blade.php文件中,我们将每个$article放在<article>标签中:

@foreach($articles as $article)

<article class="format-image group">

    <h2 class="post-title pad">

        <a href="/articles/{{ $article->id }}"> {{ $article->title }}</a>

    </h2>

    <div class="post-inner">

        <div class="post-deco">

            <div class="hex hex-small">

                <div class="hex-inner"><i class="fa"></i></div>

                <div class="corner-1"></div>

                <div class="corner-2"></div>

            </div>

        </div>

        <div class="post-content pad">

            <div class="entry custome">

                {{ $article->intro }}

            </div>

            <a class="more-link-custom" href="/articles/{{ $article->id }}"><span><i>更多</i></span></a>

        </div>

    </div>

</article>

@endforeach

然后最后就是修改articles/show.blade.php视图文件了:

@section('content')

    <article class="format-image group">

        <h2 class="post-title pad">

            <a href="/articles/{{ $article->id }}" rel="bookmark"> {{ $article->title }}</a>

        </h2>

        <div class="post-inner">

            <div class="post-content pad">

                <div class="entry custome">

                    {{ $article->content }}

                </div>

            </div>

        </div>

    </article>

@endsection

最后看看效果:

替代文字

教程的最后,基本上就可以完成一个跟本人的blog一样的小产品。

OK,稍微美化完过后,我们就可以进入我们的主题了:在Laravel中使用Forms表单。

前奏

既然我们需要创建一篇文章,我们首先还是需要将这个创建文章的页面展示出来吧,就像SF的文章撰写页面一样:http://segmentfault.com/write

所以我们需要将上一篇的内容走一遍:

注册路由,在routes.php中增加:

Route::get('article/create','[email protected]');

我们指定article/create来加载ArticleControllercreate()方法,然后我们在ArticleController创建之:

 public function create()

    {

        return view('articles.create');

    }

这个create()方法直接加载我们的create.blade.php,所以我们创建这个视图文件,来到之前的views/articles/这个文件夹中,新建create.blade.php,写上这些测试内容:

@extends('app')

@section('content')

    <h1>撰写新文章</h1>

@endsection

浏览器访问试试http://blog.dev/article/create

替代文字

一切正确加载之后,我们就开始着手我们的Forms使用了,因为创建文章的时候就是需要表单的提交,我们才可以将内容接收到,或者说几乎每一个web应用都离不开表单,哪怕是一个注册,登录页面,也都是需要表单的存在,只要你需要收集用户的信息或者希望有一些UGC,也离不开表单。所以我们开始使用Laravel的Forms表单吧。

使用illuminate/html

这里我们使用一个官方的Package:https://github.com/illuminate/html

我们通过composer来安装之:

composer require illuminate/html

静待一会,安装成功之后,我们们怎么告诉Laravel,这个Package已经安装了?或者说我们怎么将这个Package跟Laravel的整个体系结合起来呢?

通过提供Service Provider和指定Facade!这样就可以很完美地与Laravel结合了。

为什么直接叫Service Provider和Facade?因为我知道怎么翻译这两个才贴切,意会一下

在这里顺便多说一点:在PHP的很多composer的package中,都会有各个框架的不同版本,比如说HtmlPurifier这个过滤html和预防xss的package,就有这个Laravel的版本:
https://github.com/mewebstudio/Purifier ,或多或少,一些很好的package都会有Laravel的版本。

配置

那么说回Service Provider和Facade,刚开始可能对Service Provider的概念可能很迷惑,不过你现在完全不必要担心,尽管打开config/app.php这个文件看一看:

'providers' => [

            Illuminate\Foundation\Providers\ArtisanServiceProvider::class,

            Illuminate\Auth\AuthServiceProvider::class,

            Illuminate\Broadcasting\BroadcastServiceProvider::class,

            //...

            ]

你会看到providers这个数组里面会有一堆Laravel预置的Service Provider,比如我们经常使用到得Auth,Controller等,都可以在这里找到。如果你再往下拉,你还会看到一个这样的aliases数组:

'aliases' => [

    'App'       => Illuminate\Support\Facades\App::class,

    'Artisan'   => Illuminate\Support\Facades\Artisan::class,

    'Auth'      => Illuminate\Support\Facades\Auth::class,

    //...

    ]

aliases其实就是快捷方式了,一旦在这里指定了快捷方式,我们就可以在Laravel中全局使用,比如我在代码中使用Auth,其实背后我就是在用Illuminate\Support\Facades\Auth::class,然后再深入,我们其实是在用providers中的Illuminate\Auth\AuthServiceProvider::class这个。

趁上面写这些的时候illuminate/html已经下载好了:

替代文字

那么,按照上面方式,我们来配置一下我们的illuminate/html,在config/app.php中的providers添加我们的Service Provider:

Illuminate\Html\HtmlServiceProvider::class,

配置完大概长这样:

替代文字

OK,Service Provider添加好了之后,我们来添加我们的Facade,也就是在aliases这个数值后面添加:

'Form'      => Illuminate\Html\FormFacade::class,

配置完之后看看图片长这样:

替代文字

使用Forms

这两个配置好了之后,我们就可以在在我们的create.blade.php这个视图中使用它了:

@section('content')

    <h1>撰写新文章</h1>

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

    {!! Form::close() !!}

@endsection

我们加入了两行{!! Form::open() !!}{!! Form::close() !!},至于{!!类似的符号,请类比如blade的{{,不用太纠结这个。我们再来访问http://blog.dev/article/create试试:

咋一看,貌似没有什么变化,但是你要查看页面源码或者使用开发者工具检查元素的时候,就可以发现这个form元素已经创建出来了。

替代文字

不难发现,Laravel的Form还默认为我们生成一个hidden的表单(name="_token"),这个是Laravel默认对表单提交的一点安全支持。在表单提交的时候,Laravel会自动检查这个_token是否与保存在session中的_token一致,如果不一致,那就直接跳转回远页面,不允许我们提交数据。

既然Form可以正常使用了,我们就可以创建我们需要的表单了:

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

   <div class="form-group">

       {!! Form::label('title','标题:') !!}

       {!! Form::text('title',null,['class'=>'form-control']) !!}

   </div>

   <div class="form-group">

       {!! Form::label('content','正文:') !!}

       {!! Form::textarea('content',null,['class'=>'form-control']) !!}

   </div>

   <div class="form-group">

       {!! Form::submit('发表文章',['class'=>'btn btn-success form-control']) !!}

   </div>

{!! Form::close() !!}

我们在{!! Form::open() !!}加入一点东西,先来看看我们的效果:

替代文字

下面详细解释一下:

{!! Form::text('title',null,['class'=>'form-control']) !!}

拿这个来开刀吧:

  1. Form::text 表示<input type='text' />,还要一堆比如 <input type='password' />等你可以参照着写。

  2. 'title' 表示 name='title'

  3. null 表示 value=''

  4. 'class'=>'form-control' 表示class='form-control',这里可以指定idplaceholder等一系列你想指定的属性

然而在Form::open()没有指定提交路径的情况之下,默认是提交到本页面,这样对于我们的清晰分工是不太好的,因为这个页面就是用来加载视图的,而对于我们表单提交的内容,我们希望用另外的方法来处理,所以我们来写一写吧。

首先在Form::open()指定表单提交的url,直接在加入url:

{!! Form::open(['url'=>'article/store']) !!}

我们指定表单post提交到article/store这个地址,然后在routes.php注册这个路由地址:

Route::post('article/store','[email protected]');

这里注意我们使用了Route::post而不是Route::get,这是用来接收post的路由。然后顺利成章,在ArticleController中创建store()方法:

public function store()

    {

        $input = Request::all();

        return $input;

    }

在这个方法中,我们引入Laravel自带的Request并使用Request::all(),来获取所有的用户提交的过来的内容(这里指的是:_token,namecontent),如果你想获取具体某一个表单输入的内容,可以使用Request::get(),比如Request::get('title'),然后直接return来看看用户到底输入了什么内容,我们来试试:

替代文字

实现创建新文章

OK,成功拿到用户的提交的内容之后,我们需要将这些保存到数据库,怎么实现呢?在第四篇中,我们提到的Eloquentcreate()方法现在就可以派上用场了,于是我们可以写成这样:

Article::create($input);

Laravel会自动过滤_token这个提交内容。

但是创建完一篇文章之后,我们并不是想return $input,而是想重新跳转到某个页面中,比如我们的首页,因为发表完文章,我们需要看到它是否成功出线在文章列表中,所以我们最后写一下:

public function store()

    {

        $input = Request::all();

        Article::create($input);

        return redirect('/');

    }

我们直接使用Laravel的redirect()函数进行跳转,跳转到首页。这个时候,短短的三行代码就可以将我们的逻辑实现了,那么我们来试试:

替代文字

貌似成功了?但是我们觉得这个排序有点问题,最新创建的文章当然是在最上面的了,所以我们到ArticleControllerindex()方法中稍微修改一下:

public function index()

    {

        $articles = Article::latest()->get();

        return view('articles.index',compact('articles'));

    }

将原来的all()换成了latest()->get(),刷新,

替代文字
我们发现,最新的文章intro竟然空白,我们到数据库看看:
替代文字

我们发现,刚刚创建的文章的intro为空值,而published_at0000-00-00 00:00:00,这不是我们想要的,为什么会这样呢?因为我们在提交过来的时候,并没有这两个数据啊,为了解决这个问题,首先我们可以很暴力得将这两个数据在使用Article::create($input)之前配置好,比如:

public function store()

    {

        $input = Request::all();

        //下面增加两行,顺便看看Request::get的使用

        $input['intro'] = mb_substr(Request::get('content'),0,64);

        $input['published_at'] = Carbon::now();

        Article::create($input);

        return redirect('/');

    }

intro字段就直接取content字段的头64个,然后published_at就默认为创建的时间。目前开起来代码有点暴力,但是不失为一种解决方案,我们后续会使代码much cleaner。我们再来试试:

替代文字

bang,成功了,我们在看看数据库:

替代文字

到这里,我们创建一篇文章的基本流程就完成了,但是这里还有一个问题,如果你尝试在文章创建的页面什么都不填,直接提交数据,你看看会发生什么,如果不确定,你可以看看你的数据库,到底发生了什么。

下一节

鉴于最后的问题和牵涉到表单的内容,下一节貌似很顺理成章就应该说说表单验证了,在Laravel中就是Request Validation。

最后,

Happy Hacking

本文由 JellyBool 创作, 转载和引用遵循 署名-非商业性使用 2.5 中国大陆 进行许可。

共有 193 条评论

openwrtmail
修改的评论也不能少于六个字哦!
openwrtmail
修改的评论也不能少于六个字哦!
JellyBool
修改的评论也不能少于六个字哦!
lqooer 回复 JellyBool
修改的评论也不能少于六个字哦!
zhouwenbin 回复 JellyBool
修改的评论也不能少于六个字哦!
JellyBool 回复 zhouwenbin
修改的评论也不能少于六个字哦!
zhouwenbin 回复 JellyBool
修改的评论也不能少于六个字哦!
ethanzyc
修改的评论也不能少于六个字哦!
ethanzyc
修改的评论也不能少于六个字哦!
JellyBool
修改的评论也不能少于六个字哦!
malayke
修改的评论也不能少于六个字哦!
JellyBool
修改的评论也不能少于六个字哦!
JellyBool
修改的评论也不能少于六个字哦!
malayke
修改的评论也不能少于六个字哦!
JellyBool
修改的评论也不能少于六个字哦!
xuan9230
修改的评论也不能少于六个字哦!
JellyBool
修改的评论也不能少于六个字哦!
zhengmin4516
修改的评论也不能少于六个字哦!
zhengmin4516
修改的评论也不能少于六个字哦!
JellyBool
修改的评论也不能少于六个字哦!
JellyBool
修改的评论也不能少于六个字哦!
meow
修改的评论也不能少于六个字哦!
JellyBool
修改的评论也不能少于六个字哦!
meow
修改的评论也不能少于六个字哦!
JellyBool
修改的评论也不能少于六个字哦!
meow
修改的评论也不能少于六个字哦!
JellyBool
修改的评论也不能少于六个字哦!
meow
修改的评论也不能少于六个字哦!
JellyBool
修改的评论也不能少于六个字哦!
meow
修改的评论也不能少于六个字哦!
JellyBool
修改的评论也不能少于六个字哦!
meow
修改的评论也不能少于六个字哦!
JellyBool
修改的评论也不能少于六个字哦!
meow
修改的评论也不能少于六个字哦!
JellyBool
修改的评论也不能少于六个字哦!
meow
修改的评论也不能少于六个字哦!
meow
修改的评论也不能少于六个字哦!
JellyBool
修改的评论也不能少于六个字哦!
meow
修改的评论也不能少于六个字哦!
JellyBool
修改的评论也不能少于六个字哦!
meow
修改的评论也不能少于六个字哦!
woailuosj
修改的评论也不能少于六个字哦!
woailuosj
修改的评论也不能少于六个字哦!
JellyBool
修改的评论也不能少于六个字哦!
woailuosj
修改的评论也不能少于六个字哦!
openwrtmail
修改的评论也不能少于六个字哦!
taruca
修改的评论也不能少于六个字哦!
JellyBool
修改的评论也不能少于六个字哦!
taruca
修改的评论也不能少于六个字哦!
simond
修改的评论也不能少于六个字哦!
fyzzy1943
修改的评论也不能少于六个字哦!
fyzzy1943
修改的评论也不能少于六个字哦!
dudushuang
修改的评论也不能少于六个字哦!
dudushuang
修改的评论也不能少于六个字哦!
lms3344wjx
修改的评论也不能少于六个字哦!
jwwb681232a
修改的评论也不能少于六个字哦!
JellyBool
修改的评论也不能少于六个字哦!
Smile
修改的评论也不能少于六个字哦!
HappyClub成长乐园
修改的评论也不能少于六个字哦!
见到你-很高兴
修改的评论也不能少于六个字哦!
JellyBool
修改的评论也不能少于六个字哦!
xuan9230
修改的评论也不能少于六个字哦!
dotasfans
修改的评论也不能少于六个字哦!
JellyBool
修改的评论也不能少于六个字哦!
dotasfans
修改的评论也不能少于六个字哦!
hhzx
修改的评论也不能少于六个字哦!
高启松
修改的评论也不能少于六个字哦!
JellyBool
修改的评论也不能少于六个字哦!
heigh_高
修改的评论也不能少于六个字哦!
JellyBool
修改的评论也不能少于六个字哦!
axhello
修改的评论也不能少于六个字哦!
cxccxc
修改的评论也不能少于六个字哦!
qiandutianxia
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
yu119043355 回复 Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
Anonymous
修改的评论也不能少于六个字哦!
cheungboss
修改的评论也不能少于六个字哦!
zhouwenbin
修改的评论也不能少于六个字哦!
JellyBool 回复 zhouwenbin
修改的评论也不能少于六个字哦!
zhouwenbin 回复 JellyBool
修改的评论也不能少于六个字哦!
JellyBool 回复 zhouwenbin
修改的评论也不能少于六个字哦!
zhouwenbin 回复 JellyBool
修改的评论也不能少于六个字哦!
JellyBool 回复 zhouwenbin
修改的评论也不能少于六个字哦!
hehorange
修改的评论也不能少于六个字哦!
JellyBool 回复 hehorange
修改的评论也不能少于六个字哦!
yh4494
修改的评论也不能少于六个字哦!
kissgxd
修改的评论也不能少于六个字哦!
JellyBool 回复 kissgxd
修改的评论也不能少于六个字哦!
ReviveKwan
修改的评论也不能少于六个字哦!