在本章,咱們經過搭建一個很簡單的迷你博客把前面的知識再走一遍,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以後感受總體運行都有了很大的瞭解,仍是須要多動手啊!!!