Tuesday, July 14, 2015

Simple blog using Laravel - Part I

Migrations

Create articles migration:
$ php artisan make:migration create_articles_table --create="articles"
Inside database/migrations find created migration and edit:
2015_07_13_192755_create_articles_table.php
and add these lines to up() method:
Schema::create('articles', function (Blueprint $table) {
    $table->increments('id');
    $table->string('title');
    $table->text('body');
    $table->text('excerpt')->nullable();
    $table->timestamp('published_at');
    $table->timestamps();
});
To execute created migration do:
$ php artisan migrate

Routes

Edit
app\Http\routes.php
and add this line:
Route::resource('articles', 'ArticlesController');
Which is easier way and equal to manually supply all CRUD routes following REST convention like so:
Route::get('articles', 'ArticlesController@index');
Route::get('articles/create', 'ArticlesController@create');
Route::get('articles/{id}', 'ArticlesController@show');
Route::post('articles', 'ArticlesController@store');
Route::get('articles/{id}/edit', 'ArticlesController@edit');

Model

We have articles table, so lets create Article model:
$ php artisan make:model Article
Edit our model app\Article.php and add $fillable fields so we can mass assign them while creating article. Also specify published_at field inside $dates so Laravel threat this field as Carbon date object instead of simple string representation.
class Article extends Model
{
    protected $dates = ['published_at'];
    protected $fillable = [
    'title',
    'body',
    'published_at'
    ];
}

Add two rows to article table using Laravel interactive tinker tool:
$ php artisan tinker;
$ App\Article::create(['title' => 'My first article', 'body' => 'Article body', 'published_at' => Carbon\Carbon::now()]);
$ App\Article::create(['title' => 'New article', 'body' => 'New body', 'published_at' => Carbon\Carbon::now()]);
$ App\Article::all();
Update first article:
$article = App\Article::find(1);
$article->body = 'Lorem ipsum';
$article->save();
App\Article::all();
Get collection of articles:
$articles = App\Article::where('body','Lorem ipsum')->get();
Get first article:
$article = App\Article::where('body','Lorem ipsum')->first();

Controller

Let's create plain ArticlesController:
$ php artisan make:controller ArticlesController --plain
So now we will create index action to fetch list of articles.
Edit app\Http\Controllers\ArticlesController.php:
public function index()
{
    $articles = Article::latest('published_at')->published()->get();
    return view('articles.index', compact('articles'));
}
We want to use published() scope while fetching articles to get only those published until today and sort them descending from newest to oldest by published_at using latest(). So let's create published() scope in app\Article.php model. Notation is keyword scope followed by scope name, like this:
use Carbon\Carbon;
public function scopePublished($query)
{
    $query->where('published_at', '<=', Carbon::now());
}
To show details of selected article we need show() action. Edit app\Http\Controllers\ArticlesController.php:
public function show($id)
{
    $article = Article::findOrFail($id);
    return view('articles.show', compact('article'));
}

View

Inside resources folder create app.blade.php:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
</head>
<body>
<div class="container">
@yield('content')
</div>
@yield('footer')
</body>
</html>
Inside resources\articles create index.blade.php:
@extends('app')
@section('content')
<div class="col-md-12 staff-header">
<h5>Articles</h5>
</div>
<div class="col-xs-12 col-md-12">
@foreach( $articles as $article)
<article>
<h4>
<a href="{{ action('ArticlesController@show', [$article->id]) }}">{{ $article->title }}</a>
</h4>
<h6>{{ $article->body }}</h6>
<br/>
</article>
@endforeach
</div>
@stop
Inside resources\articles create show.blade.php:
@extends('app')
@section('content')
<div class="col-md-12 staff-header">
<h5>{{ $article->title }}</h5>
</div>
<div class="col-xs-12 col-md-12">
<article>
<h6>{{ $article->body }}</h6>
</article>
</div>
@stop

No comments: