Laravel5.2之Demo1——URL生成和存儲

引言:

本文基於Laravel框架作的一個URL生成和存儲demo,主要目的是學習使用Laravel框架。內容基於英文書籍《Packt.Laravel.Application.Development.Blueprints》第一章節,彷佛沒有中文版。書籍基於Laravel4的,學習時使用Laravel5.2框架開發。
 php

學習主題

該demo主要涉及以下幾個知識點:css

  1. 建立數據庫並遷移數據表html

  2. 建立表單,學習Laravelblade模板引擎java

  3. 建立名爲Link的模型Modelmysql

  4. 保存數據進入數據庫laravel

  5. 從數據庫中得到URL連接並重定向sql

一、建立數據庫並遷移數據表單

表遷移(Migrations)其實就是數據庫(Database)的版本控制,容許團隊修改數據庫架構,並保存當前數據庫最新架構信息,爲了建立並遷移建立的URL數據庫,須要作幾個步驟:數據庫


(1)、首先建立一個數據庫並定義該數據庫與Laravel的鏈接信息,Laravel框架爲數據庫鏈接提供了配置文件:/config/database.phpLaravel支持SQlite、MySQL、PostgreSQL、SQLSRV數據庫,本教程使用MySQL數據庫。json


(2)、建立一個名爲urls的數據庫,終端登入mysql服務器或者使用phpMyAdmin敲入SQL語句:CREATE DATABASE urls。可使用PHPStorm這個IDE的database模塊遠程建立urls數據庫。數組


(3)、在成功建立數據庫urls後,開始配置數據庫名稱和用戶名密碼,在/config/database.php裏配置host,database,username,password,因爲配置文件使用env()函數先讀取.env文件裏的值,因此能夠直接在.env文件裏配置。.env文件能夠從.env.example文件複製得來,如修改.env文件中值:DB_HOST=localhost,DB_DATABASE=urls,DB_USERNAME=root,DB_PASSWORD=laravel;也能夠修改/config/database.php文件爲:'host'=>'localhost','database'=> 'urls','username'=>'root','password' =>'laravel'。數據庫用戶名爲安裝MySQL時配置的。


(4)、使用LaravelArtisan CLI工具命令建立migrations遷移文件,能夠在終端進入項目根目錄輸入php artisan命令查看Artisan命令列表。如今建立一個名爲links的遷移文件:php artisan make:migration create_links_table --create=links,會在/database/migrations/文件夾下新建一個date+create_links_table.php文件,該文件源碼主要包含兩個很是重要的方法:up()/down()。當執行數據表遷移命令php artisan migrate時執行的是up()方法;當執行回滾上一次遷移命令php artisan migrate:rollback時執行的是down()方法,該命令具備破壞性會刪除links數據表。曾經遇到一個場景:須要給數據表test增長一個字段age但又要保留test表裏數據,能夠再建立一個遷移文件php artisan make:migration create_links_table --table=links,生成的遷移文件中up()方法裏引用了Schema::table()方法而不是Schema::create()方法,再添加$table->string('age')->default(0);語句,刪除原來的'id'和timestamps郵戳語句,再執行php artisan migrate遷移命令。


(5)、在建立的遷移文件內增長兩個字段:$table->text('url');$table->string('hash',400);,自動生成的$table->timestamps();語句是給數據表添加郵戳,會自動增長'created_at'/'updated_at'兩個字段,默認時間是UTC與北京時間相差8小時,能夠在config/app.php文件中修改'timezone'值爲'Asia/Shanghai'就行。再執行遷移命令php artisan migrate,若是數據庫配置沒有錯誤就會在urls數據庫裏生成links表和migrations表,migrations表記錄的是遷移記錄可不用管。

註明:能夠安裝phpstorm這個IDE,使用它的database模塊查看數據庫,說實話我的用的感受還挺順手的,固然也能夠安裝navicat premium軟件查看。

 

二、建立Form表單

(1)、在resources/views/文件夾下建立一個urls文件夾,在urls文件夾下建立一個form.blade.php文件文件名須要有blade字符串,laravel會自動識別這個文件爲blade模板文件。form模板代碼爲:

<html lang="en">
    <head>
        <title>URL Shortener</title>
        <link rel="stylesheet" href="{{asset('css/urls/style.css')}}">
    </head>
        <body>
            <div id="container">
                <h2>短連接生成器</h2>
                {{Form::open(array('url'=>'/url','method'=>'post'))}}
                {{Form::text('link', '請輸入您的網址!')}}
                {{--{{Form::text('link',Input::old('link'), array('placeholder'=>'請輸入您的網址!'))}}--}}
                {{Form::close()}}
            </div>
        </body>
    </html>

註明:個人Laravel代碼會報錯沒有Input這個類,很奇怪,那就把這一句註銷掉吧。若是你知道咋解決,請在評論留言給我,謝謝。樣式style.css文件能夠用asset()函數在public文件夾下找到路徑,在這裏就是public/css/urls/style.css。固然,也能夠不用這個Form類,直接寫<form></form>表單html代碼也行。這裏的url表示提交表單時的路由,方法爲post。在這裏使用laravelcollective/html這個組件,順便了解下怎麼在laravel中安裝組件。
這裏書中使用了laravel4.*自帶的Form類,但laravel5.*已經移除了,能夠經過composerComposer官網安裝。能夠進入官網https://laravelcollective.com/docs/5.1/html找安裝和配置方式,也能夠去packagist.org中找https://packagist.org/packages/laravelcollective/html,這裏推薦一個很是好用的網站packagist,PHP中全部組件components均可以在這裏找到並經過composer安裝。《Modern PHP》(能夠去pan.java1234.com搜到英文版的)這本書中倡導PHP軟件開發應該使用組件components方式來作,利用別人的輪子會加速開發效率,組件components可裝可卸,組件式代碼比麪條式代碼讀起來更舒服!!!
經過composer安裝也很簡單,就是在項目根目錄下的composer.json文件'require'數組中添加"laravelcollective/html": "5.2.*",,再composer update就行,安裝完laravelcollective/html後在config/app.php文件中配置這個組件的服務serviceprovider,在'providers'數組中加上Collective\Html\HtmlServiceProvider::class,,在'aliases'數組中加上'Form' => Collective\Html\FormFacade::class,'Html' => Collective\Html\HtmlFacade::class,,就能夠用這個組件輪子了,實際上不少組件也都是這麼安裝配置的。
樣式style.css代碼爲:

div#container{padding-top:100px;text-align:center;width:75%;margin:auto;border-radius:4px}
    div#container h2{font-family:Arial,sans-serif;font-size:28px;color:#555}
    div#container h3{font-family:Arial,sans-serif;font-size:28px}
    div#container h3.error{color:#a00}
    div#container h3.success{color:#0a0}
    div#container input{display:block;width:90%;float:left;font-size:24px;border-radius:5px}
    div#error,div#success{border-radius:3px;display:block;width:90%;padding:10px}
    div#error{background:#ff8080;border:1px solid red}
    div#success{background:#80ff80;border:1px solid #0f0}

balde模板頁面寫完,而後在routes.php路由文件中寫個路由:

Route::get('/url', function(){
    return view('urls.form');//urls爲建立的文件夾
});

這裏路由第二個參數爲匿名函數,直接返回視圖,固然能夠建個控制器php artisan make:controller UrlController,在控制器裏寫個getUrl()方法返回視圖,那路由就要這麼寫了:Route::get('url', 'UrlController@getUrl')
最後輸入URL:http://yourhost/url,則blade模板頁面如圖所示:

三、建立名爲Link的Model

Laravel提供了一個很是好用的ORM(Object Relationship Mapping)爲Eloquent ORM,其實就是Model層,來管理數據庫中的數據表且一一對應關係。Eloquent比較好用在於它提供了不少Feature功能模塊,這些模塊提供了許多面向對象的方法便於使用,這樣就不用寫SQL語句了,且代碼看起來也很舒服。。不過有時也推薦使用它的Query Builder查詢構造器,實際上就是SQL語句封裝的類,性能會比較高一些,我的遇到過一個場景:使用Eloquent ORM性能有點慢,致使PHP執行過長報503 Time Out,改爲Query Builder後性能高不少腳本執行很快搞定,固然各有利弊,畢竟Eloquent很強大很好用。
在項目根目錄執行Artisan命令php artisan make:model Link後,生成app/Link.php文件,這個model經過配置用來管理MySQL中的links數據表,在Link這個model裏寫上配置:

class Link extends Model
    {
        //
        protected $table = 'links';
        protected $fillable = ['url', 'hash'];
    }

$table變量配置成MySQL中links數據表的名稱,$fillable用來配置數據表字段(column)被批量建立和更新的,由於後文在保存數據進入表裏時使用Link::create([])方法來進行批量賦值的。能夠查看Model這個class源碼裏有$table和$fillable字段,這個Model類提供了許多好用的方法,有時間能夠瞅瞅。若是不須要laravel自動建立的時間能夠寫上public $timestamps = false;再執行遷移命令,links數據表裏就沒有'created_at'/'updated_at'字段了。這裏注意下:若是不寫$table變量,laravel會自動根據model名字複數來找數據表,如這個model名字是link,那就找links表。

四、保存數據進入數據庫

寫好視圖表單後,再就是寫表單的提交路由及其控制器邏輯,在控制器中引用建立好的Link這個Model往links數據表裏存數據。原文書中是直接在路由中匿名函數裏寫數據存儲邏輯,這裏我的仍是先建立一個控制器php artisan make:controller UrlController,在控制器裏寫數據存儲邏輯比較好。實際上,控制器也就是路由層route、視圖層view與模型model層的黏合劑而已,通常寫laravel代碼流程也僅此而已:如今路由裏寫好路由,再創建好model(包括建立好migrations和model,寫好數據庫鏈接配置、model配置、執行migrations表遷移),再在控制器controller裏寫好業務邏輯,返回response如blade視圖view或直接一個"hello world"字符串吧,最後要是返回view那就在resources/views裏寫個view就行。laravel框架使用也僅此而已,沒有那麼複雜,對於咱們這樣的剛剛入門,瞭解這個流程就能夠玩一玩了!!!
(1)、驗證輸入
在提交表單時都要驗證輸入數據是否符合規定,省得讓髒數據進入數據表裏,laravel提供了Validation模塊來作表單驗證而且能夠在視圖中顯示驗證錯誤信息,具體想了解下的能夠看我這篇文章:Laravel學習筆記之Validator
在驗證表單時首先須要寫驗證規則$rules,本demo僅有一個輸入且輸入要符合URL格式,那就要考慮兩個問題:怎麼獲得表單的輸入$input和怎麼寫符合URL的$rules驗證規則。首先使用驗證方法Validator::make([], []),這個方法的第一個參數是取得的表單輸入$input,第二個參數是驗證規則$rules。demo中只有一個輸入可使用Input::all()取得或者Input::get('link'),其中link爲這個輸入的name,對應表單視圖的{{Form::text('link', '請輸入您的網址!')}}這個link,$rules驗證規則這麼寫:

$rules = array(
           'link' => 'required|url'
         );

這裏'required'是輸入不能爲空,是laravel自帶的驗證規則,'url'也是laravel自帶的URL驗證規則,就是格式得符合URL格式,'|'表示且的意思。
好,如今就按照流程寫代碼:
首先:

Route::post('url', 'UrlController@postUrl');

而後在UrlController中寫上:

public function postUrl(){
    $rules = array(
       'link' => 'required|url'
     );
    //$validation = Validator::make(Input::all(),$rules);
    $validation = Validator::make(Input::get('link'),$rules);
}

這裏這個存儲變量$validation存儲了不少驗證信息,頗有用,如驗證經過($validation->passes())和驗證失敗($validation->fails()),這兩個函數返回Boolean結果,還有$validation->messages()函數返回驗證失敗後驗證信息。
若是驗證失敗,就返回URL表單提交頁面,而且帶上flash data,flash data是被刷到session中,能夠在模板視圖view中經過Session::get('XXX')獲得,下面會看到代碼。那怎樣把flash data數據刷到session中:laravel提供了with()withVariableName()方法,若是直接返回view時,$VariableName直接在模板視圖中做爲變量使用,若是是重定向view時,須要經過Session::get('VariableName')方法獲取變量值。
比較:

public function getUrl(){
        $title = 'Url Generator';
        return view('urls.form')->with('titletitle', $title);//blade模板中直接使用$titletitle變量就行,如<title>{{$titletitle}}</title>
    }
    public function postUrl(){
        $title = 'Url Generator';
        return Redirect::to('/url')->with('titletitle', $title);//這裏重定向頁面,在blade模板視圖中獲得$titletitle變量能夠這麼作,Session::get('titletitle'),檢查有無變量這麼作Session::has('titletitle')
    }

而後在postUrl()方法中寫上驗證失敗的話重定向URL表單提交頁面:

if($validation->fails()) {
         return Redirect::to('/url')
         ->withInput()
         ->withErrors($validation);
    }

這裏$errors變量在blade視圖模板中能夠直接引用就不用Session::get()了,這是由於laravel會自動把這個變量和視圖模板綁定,這$errors是個特殊的變量,在form.blade.php視圖中添加上驗證錯誤信息代碼。withInput()函數會在返回表單時在input裏填上剛剛輸入的舊數據。

(2)、將驗證信息傳到模板視圖中

@if(Session::has('errors'))
       <h3 class="error">{{$errors->first('link')}}</h3>
    @endif

first()函數返回link表單的第一個驗證錯誤信息。固然也能夠遍歷驗證信息並顯示出來:

@if(Session::has('errors'))
            <div class="alert alert-danger">
                <ul>
                    @foreach($errors->all() as $error)
                        <li>{{$error}}</li>
                    @endforeach
                </ul>
            </div>
    @endif

五、深度優化控制器並處理表單Form

代碼的else部分主要處理當驗證經過後,主要實現如下邏輯:

  • 檢查link連接是否已經在數據表裏

  • 若是link連接已經在數據表裏,返回該短鏈接

  • 若是link連接不在數據表裏,那就爲該連接建立一個hash字段

  • 根據提供數據在數據表裏插入一個記錄record

  • 返回該連接給用戶(1).使用Query Builder的where()方法,並傳入Input::get('link')參數驗證數據表裏是否已經有該連接,並鏈式使用first()方法取出第一個結果:

$link = Link::where('url','=',Input::get('link'))->first();

(2).若是數據表裏有該連接,重定向到表單頁面並帶上數據表的hash字段:

if($link) {
        return Redirect::to('/url')->withInput()->with('link',$link->hash);
    }

能夠經過$link->columnName取得數據表裏的字段值。這裏with('name','value')等同於駝峯方法withName('value')方法,上文也說明了。在form.blade視圖中也加上消息:

@if(Session::has('link'))
   <h3 class="success">
     {{Html::link(Session::get('link'),'Click here for your shortened URL')}}//Html類是laravelcollective/html這個模塊裏的類,或者直接寫個`a`超連接標籤也行
   </h3> @endif

(3).連接不在數據表裏,爲該連接建立一個hash字段,原文使用$newHash = Str::random(6)建立一個包含數字字母的字符長度爲6的字符串,再去表裏驗證該$newHash是惟一的,這樣比較麻煩,能夠直接使用Hash::make($param)就行:

else{
    $newHash = Hash::make(Input::get('link'));//根據輸入的link作hash哈希就行或者別的更簡短的輸入值
}

(4).向link數據表裏插入一個新的記錄record:

else{
    $newHash = Hash::make(Input::get('link'));//根據輸入的link作hash哈希就行或者別的更簡短的輸入值
    Link::create([
        'url' => Input::get('link'),
        'hash' => $newHash
        ]);
}

使用Link模型的create()方法建立一條record,或者:

$link = new Link();
    $link->url = Input::get('link');
    $link->hash = $newHash;
    $link->save();

以前研究過一個小點:使用create方式是須要在Link模型類中寫上$fillable指定批量賦值字段,不然報錯,而這個save方式不須要這麼作。

(5).再重定向到表單提交頁面

return Redirect::to('/url')
           ->withInput()
           ->with('link', $newHash);

這裏帶上$newHash變量是爲了後面捕獲這個變量後,根據這個變量從數據表裏查找對應的url值。

六、從數據庫中取出URL而且重定向

最後根據生成的URL獲取其hash部分,根據hash值從links數據表取出對應的URL爲了重定向,這裏英文原文也是在路由中寫邏輯,這裏也在路由裏寫邏輯:

Route::get('/url/{hash}', function($hash){
    $link = Link::where('hash',$hash)->first();
    if($link){
        return Redirect::to($link->url);
    }else{
        return Redirect::to('/url')->with('message', 'Invalid Link');
    }
})->where('hash', '[0-9a-zA-Z+]');

{hash}是一個路由參數,做爲匿名函數的參數,而且正則限制其是由數字字母組合where('hash', '[0-9a-zA-Z+]'),若是links數據表裏有數據就跳轉到這個連接去,沒有則返回message給blade模板視圖,因此form.blade模板視圖須要添加顯示:

@if(Session::has('message'))
        <h3 class="error">{{Session::get('message')}}</h3>
    @endif
相關文章
相關標籤/搜索