在本章,咱们经过搭建一个很简单的迷你博客把前面的知识再走一遍,php
只有经过一次又一次的实战才能达到炉火纯青写起代码手上带风的效果:)css
由于本实验篇幅较长,为防止发生你们作实验作到一半下次又要从新来的悲剧。html
建议非会员用户可使用实验楼提供的 Git 仓库来储存代码(点此查看使用方法),或者直接升级为会员便可直接保存环境。mysql
在开始写第一行代码以前,必定要尽可能从头至尾将咱们要作的产品设计好,避免写完又改,多写没必要要的代码。laravel
需求分析:咱们的迷你博客应该至少包含:新增/编辑/查看/删除文章,以及文章列表展现功能。
数据库分析:基于这个功能,咱们只须要一张 Articles 数据表来存放文章便可。
页面结构分析:应该使用模板继承创建一张基础模板包含:导航栏/底部信息栏/做者信息等。
最后咱们能够简单画个草图:web
此处输入图片的描述sql
3、建立路由数据库
完成这个博客大概须要如下几条路由:express
路由 | 功能 |
---|---|
文章列表页面路由 | 返回文章列表页面 |
新增文章页面路由 | 返回新增文章页面 |
文章保存功能路由 | 将文章保存到数据库 |
查看文章页面路由 | 返回文章详情页面 |
编辑文章页面路由 | 返回编辑文章页面 |
编辑文章功能路由 | 将文章取出更新后从新保存到数据库 |
删除文章功能路由 | 将文章从数据库删除 |
能够看到几乎所有是对文章的数据操做路由,针对这种状况,Laravel 提供了很是方便的办法:RESTful 资源控制器和路由。后端
打开routes.php加入以下代码:
Route::resource('articles', 'ArticlesController');
尤为注意是resource ,不是通常的get!!!
只须要上面这样一行代码,就至关于建立了以下7条路由,且都是命名路由,咱们可使用相似route(‘articles.show’) 这样的用法。
Route::get('/articles', 'ArticlesController@index')->name('articles.index');
Route::get('/articles/{id}', 'ArticlesController@show')->name('articles.show');
Route::get('/articles/create', 'ArticlesController@create')->name('articles.create');
Route::post('/articles', 'ArticlesController@store')->name('articles.store');
Route::get('/articles/{id}/edit', 'ArticlesController@edit')->name('articles.edit');
Route::patch('/articles/{id}', 'ArticlesController@update')->name('articles.update');
Route::delete('/articles/{id}', 'ArticlesController@destroy')->name('articles.destroy');
app/Http/routes.php
里面的代码:
<?php
/*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
|
| Here is where you can register all of the routes for an application.
| It's a breeze. Simply tell Laravel the URIs it should respond to
| and give it the controller to call when that URI is requested.
|
*/
Route::get('/', function () {
return view('welcome');
});
Route::resource('articles', 'ArticlesController');
利用 artisan 建立一个文章控制器:
php artisan make:controller ArticlesController
在 resources/views 目录下新建一个文件夹 layouts, 而后在 resources/views/layouts 目录下新建一个文件 app.blade.php。
打开 app.blade.php:
resources/views/layouts/app.blade.php
<!DOCTYPE html>
<html>
<head>
<title>Myweb</title>
<style type="text/css"> body{margin: 0;padding: 0;background-color: #DEDEDE;} a{text-decoration:none;} .header{padding:10px 50px 10px 50px;border-bottom: 1px solid #eeeeee;} .header>.logo{display:inline-block;} .header>.menu{display:inline-block;margin-left:20px;} .content{} .left{background-color: white;margin: 25px 300px 25px 25px;padding: 25px;box-shadow: 1px 1px 2px 1px #848484;} .right{background-color: white;width: 200px;margin: 25px;padding: 25px;box-shadow: 1px 1px 2px 1px #848484;position: absolute;top: 92px;right: 0;} .footer{padding:10px 50px 10px 50px;background-color:gray;} </style>
</head>
<body>
<!-- header -->
<div class="header">
<div class="logo">
<a href="#"><h2>Myweb</h2></a>
</div>
<div class="menu">
<a href="{{ route('articles.index') }}">Articles</a>
</div>
</div>
<div class="content">
<div class="left">
@yield('content')
</div>
<div class="right">
</div>
</div>
<!-- footer -->
<div class="footer">
<p>contact me : 1234567</p>
</div>
</body>
</html>
接下来的全部视图咱们都将继承这个视图,咱们可让控制器先返回基础视图看一下效果。
打开 ArticlesController.php:
app/Http/Controllers/ArticlesController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
class ArticlesController extends Controller {
/** * Display a listing of the resource. * * @return \Illuminate\Http\Response */
public function index() {
return view('layouts.app');
}
而后访问 localhost/articles 就能够看到基础视图了。
咱们首先建立一个 文章列表展现页,做为咱们的迷你博客首页。
在 resources/views 目录下新建一个文件夹 articles ,而后在 resources/views/articles 目录下新建一个文件 index.blade.php。
打开 index.blade.php:
resources/views/articles/index.blade.php
@extends('layouts.app') @section('content') <a href="{{ route('articles.create') }}" style="padding:5px;border:1px dashed gray;"> + New Article </a> @endsection
而后打开 ArticlesController.php 将刚才的index函数修改成正确的视图:
app/Http/Controllers/ArticlesController.php
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Http\Requests; use App\Http\Controllers\Controller; class ArticlesController extends Controller { /** * Display a listing of the resource. * * @return \Illuminate\Http\Response */ public function index() { return view('articles.index'); }
而后访问 localhost/articles 页面能够看到咱们的文章列表详情页。 固然了如今尚未任何文章,可是咱们建立了一个“新建文章”的按钮,用来新建文章,点击后会跳转到新建文章表单页面,注意这里的跳转,使用了命名路由。
<a href="{{ route('articles.create') }}" style="padding:5px;border:1px dashed gray;"> + New Article </a>
若是这时你点击新建文章,你会发现跳到了空白页,由于如今实际上是跳到了 ArticlesController 的 create() 方法里,而这个方法如今是空白的,因此就出现了空白页,咱们打开ArticlesController.php 来补全这个方法。
app/Http/Controllers/ArticlesController.php
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Http\Requests; use App\Http\Controllers\Controller; class ArticlesController extends Controller { . . . /** * Show the form for creating a new resource. * * @return \Illuminate\Http\Response */ public function create() { return view('articles.create'); }
相应的,在resources/views/articles 目录下建立一个视图create.blade.php。
resources/views/articles/create.blade.php
@extends('layouts.app')
@section('content')
<form action="{{ route('articles.store') }}" method="post">
{{ csrf_field() }}
<label>Title</label>
<input type="text" name="title" style="width:100%;" value="{{ old('title') }}">
<label>Content</label>
<textarea name="content" rows="10" style="width:100%;">{{ old('content') }}</textarea>
<button type="submit">OK</button>
</form>
@endsection
注意上面代码中的 {{ csrf_field() }}
,这是 Laravel 的 CSRF 保护机制,你应该为你的每一个表单添加这样一行代码,以使你的网站不受到跨网站请求伪造 攻击,详情参考官方文档。
此时咱们访问localhost/articles 点击新建文章就能够看到新建文章的表单了。
此时若是你填写新建文章表单点击提交也会跳到一个空白页面,一样的道理,由于咱们后续的控制器代码还没写。
要实现文章存储,首先要配置数据库,建立数据表,建立模型,而后再完成存储逻辑代码。
(保存环境的同窗可跳过这一步)根据上次实验学过的知识快速完成配置:
sudo service mysql start mysql -u root -p create database myweb;
.env文件
DB_HOST=localhost
DB_DATABASE=myweb
DB_USERNAME=root
DB_PASSWORD=
利用 artisan 命令生成迁移:
php artisan make:migration create_articles_table
而后打开迁移文件:
database/migrations/XXXX_creat_articles_table.php
生成的迁移文件
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateArticlesTable extends Migration {
/** * Run the migrations. * * @return void */
public function up() {
Schema::create('articles', function (Blueprint $table) {
$table->increments('id');
$table->string('title');
$table->longText('content')->nullable();
$table->timestamps();
});
}
/** * Reverse the migrations. * * @return void */
public function down() {
Schema::dropIfExists('articles');
}
}
咱们建立了一张 articles 表,包含递增的 id 字段,字符串title字段,长文本content字段,和时间戳。 执行数据库迁移:
php artisan migrate
利用 artisan 命令建立模型:
php artisan make:model Article
打开模型文件,输入如下代码:
app/Article.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Article extends Model {
protected $table = 'articles';
protected $fillable = [
'title', 'content',
];
}
指定了数据表的名称和可写字段。
打开 ArticlesController.php 控制器,找到 store() 方法。
app/Http/Controllers/ArticlesController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use App\Article;// <---------注意这里
class ArticlesController extends Controller {
.
.
.
/** * Store a newly created resource in storage. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */
public function store(Request $request) {
$this->validate($request, [
'title' => 'required|max:50',
]);
$article = Article::create([
'title' => $request->title,
'content' => $request->content,
]);
return redirect()->route('articles.index');
}
由于这段代码中用到了Eloquent 模型的构造器用法,因此须要引入咱们以前建立的模型。
use App\Article;
在收到表单传过来的数据时,能够先对表单数据进行验证:
$this->validate($request, [
'title' => 'required|max:50',
]);
最后完成文章的建立,而后重定向到文章列表页:
$article = Article::create([
'title' => $request->title,
'content' => $request->content,
]);
return redirect()->route('article.index');
至此,新增文章功能就完成了,打开浏览器,访问 localhost/articles 点击新建文章,完成表单,点击添加。
添加后若是跳到了文章列表页,就说明成功了!
可是此时,咱们并不知道是否是真的添加成功了,咱们能够去数据库里看一下是否有了刚刚插入的数据:
mysql -u root -p
use myweb;
select * from articles;
能够看到咱们刚刚建立的一篇文章已经被成功的写入了数据库。
完成了添加文章功能后,就能够实现咱们的文章列表展现页了。
打开 ArticlesController.php 找到 index() 方法,添加代码以下:
app/Http/Controllers/ArticlesController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use App\Article;
class ArticlesController extends Controller {
/** * Display a listing of the resource. * * @return \Illuminate\Http\Response */
public function index() {
$articles = Article::orderBy('created_at','desc')->get();
return view('articles.index', compact('articles'));
}
取出了所有的文章并根据 created_at (建立时间)倒序排列,而后传给视图。
如今咱们就能够在视图文件中读取所有的文章并显示了。
转到文章列表展现页:
resoureces/views/articles/index.blade.php
@extends('layouts.app')
@section('content')
<a href="{{ route('articles.create') }}" style="padding:5px;border:1px dashed gray;">
+ New Article
</a>
@foreach ($articles as $article)
<div style="border:1px solid gray;margin-top:20px;padding:20px;">
<h2>{{ $article->title }}</h2>
<p>{{ $article->content }}</p>
</div>
@endforeach
@endsection
添加了一段循环输出的代码。
如今访问localhost/articles,能够看到文章正确的显示了出来。
编辑文章表单其实和以前建立的新建文章表单很相似,只是须要额外将现有的数据读取出来填在表单上。
首先咱们在文章列表页的每一个文章上添加一个编辑按钮:
resoureces/views/articles/index.blade.php
@extends('layouts.app')
@section('content')
<a href="{{ route('articles.create') }}" style="padding:5px;border:1px dashed gray;">
+ New Article
</a>
@foreach ($articles as $article)
<div style="border:1px solid gray;margin-top:20px;padding:20px;">
<h2>{{ $article->title }}</h2>
<p>{{ $article->content }}</p>
<a href="{{ route('articles.edit', $article->id ) }}">Edit</a>
</div>
@endforeach
@endsection
而后打开 ArticlesController.php 添加相应的逻辑代码:
app/Http/Controllers/ArticlesController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use App\Article;
class ArticlesController extends Controller {
/** * Show the form for editing the specified resource. * * @param int $id * @return \Illuminate\Http\Response */
public function edit($id) {
$article = Article::findOrFail($id);
return view('articles.edit', compact('article'));
}
而后建立对应视图文件:
在 resources/views/articles 目录下新建一个文件 edit.blade.php 。
打开 edit.blade.php:
resources/views/articles/edit.blade.php
@extends('layouts.app')
@section('content')
<form action="{{ route('articles.update', $article->id) }}" method="post">
{{ csrf_field() }}
{{ method_field('PATCH') }}
<label>Title</label>
<input type="text" name="title" style="width:100%;" value="{{ $article->title }}">
<label>Content</label>
<textarea name="content" rows="10" style="width:100%;">{{ $article->content }}</textarea>
<button type="submit">OK</button>
</form>
@endsection
注意这段代码中的{{ method_field('PATCH') }}
,这是跨站方法伪造,HTML 表单没有支持 PUT、PATCH 或 DELETE 动做。因此在从 HTML 表单中调用被定义的 PUT、PATCH 或 DELETE 路由时,你将须要在表单中增长隐藏的 _method 字段来伪造该方法,详情参考 官方文档。
另外一种更通俗点的解释!!!连接
你们可能注意到了这句代码 {{ method_field(‘DELETE’) }},这是什么意思呢?这是 Laravel 特有的请求处理系统的特殊约定。虽然 DELETE 方法在 RFC2616 中是能够携带 body 的(甚至 GET 方法都是能够携带的),可是因为历史的缘由,很多 web server 软件都将 DELETE 方法和 GET 方法视做不可携带 body 的方法,有些 web server 软件会丢弃 body,有些干脆直接认为请求不合法拒绝接收。因此在这里,Laravel 的请求处理系统要求全部非 GET 和 POST 的请求所有经过 POST 请求来执行,再将真正的方法使用 _method 表单字段携带给后端代码。上面小做业中的小坑即是这个,PUT/PATCH 请求也要经过 POST 来执行。
另外,这里还有一些小问题:PUT/PATCH 请求经过 POST 方法执行仅限于 form 提交,对 Ajax 请求目前来看是无效的,看来我要去给 Laravel 提交一个 patch 了。
这个表单将会把数据传到 update() 方法中,因此接下来咱们补全 update() 方法。
app/Http/Controllers/ArticlesController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use App\Article;
class ArticlesController extends Controller {
.
.
.
/** * Update the specified resource in storage. * * @param \Illuminate\Http\Request $request * @param int $id * @return \Illuminate\Http\Response */
public function update(Request $request, $id) {
$this->validate($request, [
'title' => 'required|max:50',
]);
$article = Article::findOrFail($id);
$article->update([
'title' => $request->title,
'content' => $request->content,
]);
return back();
}
到此,编辑文章功能就完成了,点击编辑后将出现编辑表单,输入新的内容后点击 “OK” 就能够成功更新数据。
首先咱们在文章列表页的每一个文章上添加一个删除按钮:
resoureces/views/articles/index.blade.php
@extends('layouts.app') @section('content') <a href="{{ route('articles.create') }}" style="padding:5px;border:1px dashed gray;"> + New Article </a> @foreach ($articles as $article) <div style="border:1px solid gray;margin-top:20px;padding:20px;"> <h2>{{ $article->title }}</h2> <p>{{ $article->content }}</p> <a href="{{ route('articles.edit', $article->id ) }}">Edit</a> <form action="{{ route('articles.destroy', $article->id) }}" method="post" style="display: inline-block;"> {{ csrf_field() }} {{ method_field('DELETE') }} <button type="submit" style="color: #F08080;background-color: transparent;border: none;">Delete</button> </form> </div> @endforeach @endsection
而后打开 ArticlesController.php 添加相应的逻辑代码:
app/Http/Controllers/ArticlesController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use App\Article;
class ArticlesController extends Controller {
.
.
.
/** * Remove the specified resource from storage. * * @param int $id * @return \Illuminate\Http\Response */
public function destroy($id) {
$article = Article::findOrFail($id);
$article->delete();
return back();
}
删除功能这样就作好了,如今访问文章列表展现页 localhost/articles 点击删除按钮,能够看到文章被删除。
最后,让咱们添加做者信息。
打开基础视图:
resources/views/layouts/app.blade.php
<!-- header -->
<div class="header">
<div class="logo">
<a href="#"><h2>Myweb</h2></a>
</div>
<div class="menu">
<a href="{{ route('articles.index') }}">Articles</a>
</div>
</div>
<div class="content">
<div class="left">
@yield('content')
</div>
<div class="right">
<!-- 这里 -->
<div style="padding:20px;border:1px solid black;">
<h3>Author</h3>
<p>name : SadCreeper</p>
<p>age : 22</p>
<p>Tel : 150-XXXX-XXXX</p>
</div>
<!-- 这里 -->
</div>
</div>
所有完成了!
这个我以前的照片都是已经编辑好的了,再贴一次!!!
中间仍是出现了好多问题,多数是由于粗心形成的,练习了这个demo以后感受总体运行都有了很大的了解,仍是须要多动手啊!!!