Laravel 5系列教程八:queryScope 和 setAttribute

原文來自 https://laravist.com/article/16php

免費視頻教程地址 https://laravist.com/series/laravel-5-basic

Laravist是我剛剛上線的Laravel社區,有任何與Laravel相關的問題能夠到這裏來問我,我會盡力去幫你們解決問題,後期會嘗試錄製一些視頻教程,形式大概是這樣的laravel

https://laravist.com/lesson/1數據庫

直接就是按照上一節所說的那樣,咱們來講說queryScope和setAttribute在laravel的用法。app

關於應用場景

這裏我首先是想向你們簡單說說這兩個知識點得應用場景是什麼,咱們在開發的時候,老是但願有一種偷懶的方式,因此考慮如下這兩個場景:less

  1. 數據在存入數據庫的時候須要進行預先處理,好比考慮一個簡單地例子:咱們在保存用戶的登陸密碼的時候,都是須要將密碼用某種方式加密事後在寫入數據庫的,咱們難道在每一次在提交表單過來以後都對傳過來的數據進行一次數據加密麼?能不能有一種自動完成對密碼入庫前就加密的機制呢?這樣咱們在處理表單的時候就不用關心密碼加密的問題了優化

  2. 想想咱們在向用戶展現的數據是否是基本上都是從數據庫取的呢?那麼每每咱們會有不少的查詢語句,在這樣的狀況之下不少的查詢語句能夠就會重複,可是在寫代碼這一行中,一旦出現多個重複,基本上就會有優化方式存在,因此這個時候queryScope就派上用場了this

setAttributes

以前,咱們都是將published_at設置爲文章建立的日期:加密

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

然而這並非咱們想要的,咱們但願有一種能夠控制的方式,好比在表單之中設置文章的發佈日期,因此,咱們來實現一下:首先將published_at這個字段放到咱們的form之中,在create.blade.php中,加入published_at 輸入框輸入:spa

<div class="form-group">
{!! Form::label('published_at','發佈日期') !!}
{!! Form::input('date','published_at',date('Y-m-d'),['class'=>'form-control']) !!}
</div>

這一段代碼加在textarea後面,這裏使用了Form::input(),這個方法,由於Form這個類沒有相似Form::date()指定date的方法,因此咱們使用Form::input()並指定input的類型爲date,並使用date('Y-m-d')來指定默認值爲文章發佈當天,可是咱們能夠修改,咱們來看看咱們的頁面如今是什麼樣的:3d

替代文字

這裏咱們能夠看到咱們拿到了published_at這個字段了,這個時候,能夠修改一下ArticleController中的store()方法的代碼了:

$input = $request->all();
$input['intro'] = mb_substr($request->get('content'),0,64);
Article::create($input);
return redirect('/');

咱們刪除了$input['published_at'] = Carbon::now();這一行代碼,而後嘗試建立一篇文章來看看:

替代文字

OK,到這裏,文章能夠建立成功了,可是若是咱們看看數據庫當中的數據:

替代文字

這裏的日期設置成的格式並非理想的模式,有沒有一種方式能夠將其設置爲跟created_atupdated_at同樣的呢?時分秒均可以知道的呢?這個時候就可使用setAttribute來完成了,在Article.php中添加下面的方法:

public function setPublishedAtAttribute($date)
{
    $this->attributes['published_at'] = Carbon::createFromFormat('Y-m-d',$date);
}

這裏注意這個寫法set+字段名+Attribute,還有的就是使用駝峯法。好比你要加密密碼的時候能夠這樣:

public function setPasswordAttribute($passowrd)
{
    $this->attributes['password'] = Hash::make($passowrd);
    //僅僅是舉例
}

這裏咱們使用了Carbon這個類,由於咱們還想將published_at字段做爲Carbon對象來處理,這樣後期會有很大的好處。注意在文件頭部使用use Carbon\Carbon;來引入Carbon。這個時候咱們再來發表一次:

替代文字

再來看看數據庫:

替代文字

這樣一來格式是對了,那麼再來爲Article.php添加一行代碼使published_at做爲Carbon對象來處理:

protected $dates = ['published_at'];

對這樣就完成了,關於更多地Carbon好處和使用特性,咱們在後面再說。

queryScope

上面實現了用published_at實現了文章的發佈日期,可是如今的文章展現仍是原來的樣式,這並非咱們想要的結果,由於咱們剛剛設置發表日期爲9-12的文章(寫文章的時候爲9-08)也展現出來了,咱們得限制一下。首先咱們能夠在查詢的時候直接實現,好比在ArticleControllerindex()方法中將查詢語句寫成這樣:

$articles = Article::where('published_at','<=',Carbon::now())->latest()->get();

咱們使用where()直接限制published_at時間小於或等於當前時間的文章才進行顯示,看看效果:

替代文字

發如今將來時間發佈的文章確實隱藏了,這樣貌似已經達到了目的,爲何還要引入qeuryScope這個用法呢?這是由於考慮到代碼的重用性,好比咱們要是多個地方使用到Article::where('published_at','<=',Carbon::now())這個條件限制呢,咱們有沒有一種方式能夠將查詢語句寫成相似下面這種形式呢?

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

就是直接使用published()這個自定義的方法來代替where('published_at','<=',Carbon::now())呢,這樣代碼可讀性也會更好。

因此咱們就來講說,queryScope的用法了,想一想咱們以前設置published_at這個字段的目的:

咱們但願能夠對文章進行簡單地管理,好比咱們在寫系列文章的時候,有可能一天寫了好幾篇,可是這種時候其實咱們發一篇文章就行了,天天消化一篇文章就很不錯了,因此做爲做者,我並不想還沒到發佈日期的文章就展現給用戶看,可是,我寫了文章也想把它存入數據庫,讓它在該發佈的日期自動顯示,這樣就行了。因而,咱們能夠好好利用一下published_at這個字段

在咱們的Article.php中增長下面的方法:

public function scopePublished($query)
{
    $query->where('published_at','<=',Carbon::now());
}

這裏注意一下寫法scope+自定義的方法名字,還有就是一如既往的駝峯法。好比咱們想使用published()這個方法,就定義爲scopePublished($query)。這個時候就能夠真正的使用上面說的查詢了,在ArticleControllerindex()方法中:

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

再去看看效果,相信你刷新以後仍是同樣的。

總結

又是最後的結尾了,這裏咱們簡單的介紹了queryScope和setAttribute的用法,下一節打算說說Eloquent的一個重要的內容:Eloquent Relationship。那個時候也就會愈來愈以爲laravel的強大了。

最後:Happy Hacking

相關文章
相關標籤/搜索