Home > Article > Backend Development > Laravel 5 Basics (10) - Date, Mutator and Scope
In our previous solution, directly assigning the value of published_at to the current date is actually a temporary solution. We need to set the publication date, which may not be published until 2 days in the future. Let us modify this problem.
First modify the controller:
<code> public function store() { Article::create(Request::all()); return redirect('articles'); }</code>
Then modify the view and add the release date field
<code>@extends('layout') @section('content') <h1>Write a New Article</h1> <hr/> {{--使用我们添加的 illuminate\html 开源库--}} {!! Form::open(['url' => 'articles']) !!} <div class="form-group"> {!! Form::label('title', 'Title:') !!} {!! Form::text('title', null, ['class' => 'form-control']) !!} </div> <div class="form-group"> {!! Form::label('body', 'Body:') !!} {!! Form::textarea('body', null, ['class' => 'form-control']) !!} </div> <div class="form-group"> {!! Form::label('published_at', 'Publish On:') !!} {!! Form::input('date', 'published_at', date('Y-m-d'), ['class' => 'form-control']) !!} </div> <div class="form-group"> {!! Form::submit('Add Article', ['class' => 'btn btn-primary form-control']) !!} </div> {!! Form::close() !!} @stop</code>
ok, let’s add a new article and set the date to a day in the future, but the article will be displayed directly at the beginning, which is not what we need. We need to show it on that day. Of course, we need to be more specific, such as displaying it at 8:00 in the morning instead of 0 o'clock. We can add a mutator (that is, a property setter in other languages) to modify our model
<code><?php namespace App; use DateTime; use Illuminate\Database\Eloquent\Model; class Article extends Model { protected $fillable = [ 'title', 'body', 'published_at' ]; //属性设置其要遵守格式约定 // set属性Attribute public function setPublishedAtAttribute($date) { $this->attributes['published_at'] = Carbon::createFromFormat('Y-m-d', $date)->hour(8)->minute(0)->second(0); } }</code>
Add a new record, check the database, we have set the time correctly, but our homepage still shows future published articles, we modify it.
<code> public function index() { //$articles = Article::latest('published_at')->get(); $articles = Article::latest('published_at')->where('published_at', '<=', Carbon::now())->get(); return view('articles.index', compact('articles')); }</code>
The above solution works, but the query statement is too long. We can use the scope provided by Laravel to simplify our work. The so-called scope can be understood as the intermediate query result used in the query process. For example, if we define a published scope, it can return all currently published articles, allowing us to modify the model.
<code> //设置scope,遵守命名规则 public function scopePublished($query) { $query->where('published_at', '<=', Carbon::now()); }</code>
Modify the controller to use scope
<code> public function index() { //$articles = Article::latest('published_at')->get(); //$articles = Article::latest('published_at')->where('published_at', '<=', Carbon::now())->get(); $articles = Article::latest('published_at')->published()->get(); return view('articles.index', compact('articles')); }</code>
The results are the same, but in complex queries we can use scope to break down our tasks, or reuse queries.
Let’s add a new query to query all articles that have not been published yet. Add scope to model
<code> public function scopeUnpublished($query) { $query->where('published_at', '>', Carbon::now()); }</code>
Modify the controller to use unpulished
<code> public function index() { //$articles = Article::latest('published_at')->get(); //$articles = Article::latest('published_at')->where('published_at', '<=', Carbon::now())->get(); //$articles = Article::latest('published_at')->published()->get(); $articles = Article::latest('published_at')->Unpublished()->get(); return view('articles.index', compact('articles')); }</code>
one more thing! If we use dd($article->published_at)
in the show
method, the result is different from dd($article->created_at);
. In the former we make own field, which is automatically generated via $table->timestamp()
in CreateArticleTable
. The automatically generated field is displayed as Carbon
type, while ours is string. There are many advantages to using the Crabon type. For example, you can output dd($article->created_at->diffForHumans());
, this kind of 1 hour ago
result, but our published_at
cannot. How to modify it? Modify the model and tell laravel that published_at
is the date.
<code> protected $dates = ['published_at'];</code>
Using dd($article->published_at->diffForHumans());
again, the result shows 3 days from now
, Bingo!
The above has introduced the basics of Laravel 5 (10) - Date, Mutator and Scope, including the content. I hope it will be helpful to friends who are interested in PHP tutorials.