How to Create a Blog with Laravel 5+ Part 5 (CRUD Post & Page) Part 2

Advertisement

This is just an incremental part and the part 2 of our Create, Read, Update and Delete (CRUD) records from Post table, on previous part which is Create a Blog with Laravel 5+ Part 5 (CRUD Post & Page) Part 1 that focuses on CRUD Post, this part aims to focus on CRUD Page, Page Controller and Views and update header section that display pages menu items.

Let’s get started

In our Database Schema Design Post and Page does share the same database table so our code here does not make much difference from the previous Part, that also mean we have the same Database Migration and Model.

At this stage, you might be thinking “oh I’m using different Database Schema design and wanted to add, rename or change order to my Database Table column, what now?” it’s okay Laravel got you covered, use the command below to create new migration but instead of creating a new table the command below will only update the previously generated migration, note the --table flag.


php artisan make:migration add_votes_to_users_table --table=users

views/pages

Here I’ve added new blade files for our form and record display.


|-- frontpage.blade.php		// I'm new to your eyes, isn't? that is because I'm actually new, I'm used to display site front page, for few reason, index.blade.php is now used to display lists of added pages.
|-- create.blade.php
|-- edit.blade.php
|-- index.blade.php
|-- show.blade.php

PagesController.php

This is where the CRUD happens, I’ve added comments, so I would not go each line of code later, I’ve also included in the comment other alternatives which you may like or wanted to try.

It still contains lists of static pages though, we’ll work on that later.


<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use App\Http\Controllers\Controller;
use App\Http\Requests;
use App\Post;
use Session;

class PagesController extends Controller
{

    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        // Fetch records in pagination so only 10 pages per page
        // To get all records you may use get() method
        $pages = Post::where('post_type', 'page')->paginate( 10 );

        return view('pages.index', ['pages' => $pages]);
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        // Directly display `pages.create` view blade file
        return view('pages.create');
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        // Validate and filter user inputted data
        // Refer to `References` for more info
        $this->validate($request, [
            'post_title'        => 'required',
            'post_slug'         => 'required|alpha_dash|max:200|unique:posts,post_slug',
            'post_content'      => 'required',
        ]);

        // Create a new Post Model initialization
        // There are many ways to coke an Egg and same in storing data to database in Laravel
        // You might use or prefer this one https://laravel.com/docs/5.4/queries#inserts
        // I just love using Eloquent
        $page = new Post;

        $page->author_ID        = $request->author_ID;
        $page->post_type        = $request->post_type;
        $page->post_title       = $request->post_title;
        $page->post_slug        = $request->post_slug;
        $page->post_content     = $request->post_content;

        $page->save();
        
        // Store data for only a single request and destory
        Session::flash( 'sucess', 'Page published.' );

        // Redirect to `pages.show` route
        // Use route:list to view the `Action` or where this routes going to
        return redirect()->route('pages.show', $page->id);
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        $page = Post::findOrFail( $id );

        return view('pages.show', [ 'page' => $page ]);
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function edit($id)
    {
        $page = Post::findOrFail( $id );

        return view('pages.edit', [ 'page' => $page ]);
    }

    /**
     * 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, [
            'post_title'        => 'required',
            'post_slug'         => 'required|alpha_dash|max:200|unique:posts,post_slug,'.$id,
            'post_content'      => 'required',
        ]);

        // You might prefer to use this one instead https://laravel.com/docs/5.4/queries#updates
        // You choose
        $page = Post::findOrFail($id);

        $page->author_ID        = $request->input('author_ID');
        $page->post_type        = $request->input('post_type');
        $page->post_title       = $request->input('post_title');
        $page->post_slug        = $request->input('post_slug');
        $page->post_content     = $request->input('post_content');

        $page->save();

        Session::flash('success', 'Page updated.');

        return redirect()->route('pages.edit', $id);
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        // Retrieve records and throw an exception if a model is not found
        $page = Post::findOrFail( $id );

        // https://laravel.com/docs/5.4/queries#deletes
        $page->delete();
        
        Session::flash('success', 'Page deleted.');
        
        return redirect()->route('pages.index');
    }


    /**
     * Front page
     */
    public function getIndex() {
        $posts = Post::paginate( 6 );

        // It replaces the previous `index.blade.php` blade file that is now used in displaying lists of added pages
        return view('pages.frontpage', [ 'posts' => $posts ]);
    }

    /**
    * Show case page
    */
    public function getShowCase() {
        return view('pages.showcase');
    }

    /**
    * Services page
    */
    public function getServices() {
        return view('pages.services');
    }

    /**
    * Contact page
    */
    public function getContact() {
        return view('pages.contact');
    }

}

frontpage.blade.php

This replace our previous index.blade.php that is now use to display lists of added Pages records

frontpage.blade.php dynamically displays recently added post right in our Blog front page.


@extends('main')

@section('title', '| Blog Tutorial')

@section('content')
    <div class="blog-header">
        <h1 class="blog-title">The Bootstrap Blog</h1>
        <p class="lead blog-description">The official example template of creating a blog with Bootstrap.</p>
    </div>
    
    <div class="row">
        <div class="col-sm-8 blog-main">
            
            @if( $posts->count() )
                @foreach( $posts as $post )
                    
                    <div class="blog-post">
                        <h2 class="blog-post-title">{{ $post->post_title }}</h2>
                        <p class="blog-post-meta">{{ date('M j, Y', strtotime( $post->created_at )) }} by <a href="#">{{ $post->author_ID }}</a></p>
                    
                        <div class="blog-content">
                            {!! nl2br( $post->post_content ) !!}
                        </div>
                    </div>

                @endforeach
            @else

                <p>No post added yet!</p>

            @endif

            {{-- Display pagination only if more than the required pagination --}}
            @if( $posts->total() > 6 )
                <nav>
                    <ul class="pager">
                        @if( $posts->firstItem() > 1 )
                            <li><a href="{{ $posts->previousPageUrl() }}">Previous</a></li>
                        @endif
                        
                        @if( $posts->lastItem() < $posts->total() )
                            <li><a href="{{ $posts->nextPageUrl() }}">Next</a></li>
                        @endif
                    </ul>
                </nav>
            @endif

        </div><!-- /.blog-main -->
        
        <!--Sidebar-->
        @include('partials._sidebar')

    </div><!-- /.row -->
@endsection
Advertisement

index.blade.php

This blade file is used to display lists of added pages from the database.


@extends('main')

@section('title', '| Pages')

@section('content')

    <div class="container">
        
        {{-- Check if current user is logged-in or a guest --}}
        @if (Auth::guest())
            
            <p class="mt-5">Cheatn?, please <a href="/login/">login</a> to continue.</p>
            
        @else
            
            <div class="blog-header">
                <h1 class="blog-title">Pages <a class="btn btn-sm btn-primary" href="{{ route('pages.create') }}">Add New</a></h1>
            </div>
            
            <div class="row">
                <div class="col-md-12">
                    
                    <table class="table">
                        <tr>
                            <th>Title</th>
                            <th>Author</th>
                            <th>Content</th>
                            <th>Date</th>
                            <th>&nbsp;</th>
                        </tr>
                        <tr>
                            {{-- Blade if and else --}}
                            @if( $pages->count() )
                                {{-- Blade foreach --}}
                                @foreach( $pages as $page )
                                    <tr>
                                        <td>
                                            <strong>
                                                <a href="{{ route('pages.edit', $page->id) }}">
                                                    {{ $page->post_title }}
                                                </a>
                                            </strong>
                                        </td>
                                        <td>{{ $page->author_ID }}</td>
                                        <td>
                                            @if ( strlen( $page->post_content ) > 60 )
                                                {{ substr( $page->post_content, 0, 60 ) }} ...
                                            @else
                                                {{ $page->post_content }}
                                            @endif
                                        </td>
                                        <td>Published {{ date( 'j/m/Y', strtotime( $page->created_at ) ) }}</td>
                                        <td>
                                            <form class="d-inline" action="{{ route('pages.destroy', $page->id) }}" method="POST">
                                                {{ csrf_field() }}
                                                {{ method_field('DELETE') }}

                                                <input type="submit" value="Delete" class="btn btn-sm btn-danger" />
                                            </form>

                                            <a class="btn btn-sm btn-info" href="{{ route('pages.edit', $page->id) }}">Edit</a>
                                        </td>
                                    </tr>
                                @endforeach
                            @else
                                
                                <tr>
                                    <td colspan="5">No page has been added yet!</td>
                                </tr>

                            @endif
                        </tr>
                    </table>

                    {{ $pages->links() }}

                </div>
            </div>

        @endif

    </div>
    
@endsection

create.blade.php

This file is used to create a new page, typically this file contains HTML form.


@extends('main')

@section('title', '| Add New Page')

@section('content')

	<div class="container">
		
		{{-- Check if current user is logged-in or a guest --}}
		@if (Auth::guest())
			
			<p class="mt-5">Please <a href="/login/">login</a> to add a new post.</p>
			
		@else
			
			<div class="blog-header">
		        <h1 class="blog-title">Add New Page</h1>
		    </div>

			<div class="row">
				<div class="push-md-2 col-md-8">
					
					<form action="{{ route('pages.store') }}" method="POST">
						{{ csrf_field() }}
						<input type="hidden" name="author_ID" value="{{ Auth::id() }}" />
						<input type="hidden" name="post_type" value="page" />
						
						<div class="form-group{{ $errors->has('post_title') ? ' has-error' : '' }}">
							<label for="post_title">Title</label> <br/>
							<input type="text" name="post_title" id="post_title" value="{{ old('post_title') }}" />
							
							@if ($errors->has('post_title'))
	                            <span class="help-block">
	                                <strong>{{ $errors->first('post_title') }}</strong>
	                            </span>
	                        @endif
						</div>

						<div class="form-group{{ $errors->has('post_slug') ? ' has-error' : '' }}">
							<label for="post_slug">Slug</label> <br/>
							<input type="text" name="post_slug" id="post_slug" value="{{ old('post_slug') }}" />

							@if ($errors->has('post_slug'))
	                            <span class="help-block">
	                                <strong>{{ $errors->first('post_slug') }}</strong>
	                            </span>
	                        @endif
						</div>
						
						<div class="form-group{{ $errors->has('post_content') ? ' has-error' : '' }}">
							<label for="post_content">Content</label> <br/>
							<textarea name="post_content" id="post_content" cols="80" rows="6">{{ old('post_content') }}</textarea>

							@if ($errors->has('post_content'))
	                            <span class="help-block">
	                                <strong>{{ $errors->first('post_content') }}</strong>
	                            </span>
	                        @endif
						</div>
						
						<div class="form-group">
							<input type="submit" class="btn btn-primary" value="Publish" />
							<a class="btn btn-primary" href="{{ route('pages.index') }}">Cancel</a>
						</div>
					</form>

				</div>
			</div>

		@endif

	</div>
	
@endsection

edit.blade.php


@extends('main')

@section('title', '| Edit Page')

@section('content')
	
	<div class="container">
		
		{{-- Check if current user is logged-in or a guest --}}
		@if (Auth::guest())
			
			<p class="mt-5">Cheatn?, please <a href="/login/">login</a> to continue.</p>
			
		@else
			<div class="blog-header">
		        <h1 class="blog-title">Edit Page <a class="btn btn-sm btn-primary" href="{{ route('pages.show', $page->id) }}">Preview Changes</a></h1>
		    </div>

			<div class="row">
				<div class="push-md-2 col-md-8">
					
					{{--
						Check route:list for `posts.update` for more info
						URL is posts/{page}, `{page}` meaning that we have to supply ID
					--}}
					<form action="{{ route('pages.update', $page->id) }}" method="POST">
						{{ csrf_field() }}
						
						{{--
							HTML forms do not support PUT, PATCH or DELETE actions.
							So, when defining PUT, PATCH or  DELETE routes that are called from an HTML form,
							you will need to add a hidden _method field to the form.
						--}}
						{{ method_field('PUT') }}
						
						<input type="hidden" name="author_ID" value="{{ Auth::id() }}" />
						<input type="hidden" name="post_type" value="page" />
						
						<div class="form-group{{ $errors->has('post_title') ? ' has-error' : '' }}">
							<label for="post_title">Title</label> <br/>
							<input type="text" name="post_title" id="post_title" value="{{ $page->post_title }}" />
							
							@if ($errors->has('post_title'))
	                            <span class="help-block">
	                                <strong>{{ $errors->first('post_title') }}</strong>
	                            </span>
	                        @endif
						</div>

						<div class="form-group{{ $errors->has('post_slug') ? ' has-error' : '' }}">
							<label for="post_slug">Slug</label> <br/>
							<input type="text" name="post_slug" id="post_slug" value="{{ $page->post_slug }}" />

							@if ($errors->has('post_slug'))
	                            <span class="help-block">
	                                <strong>{{ $errors->first('post_slug') }}</strong>
	                            </span>
	                        @endif
						</div>
						
						<div class="form-group{{ $errors->has('post_content') ? ' has-error' : '' }}">
							<label for="post_content">Content</label> <br/>
							<textarea name="post_content" id="post_content" cols="80" rows="6">{{ $page->post_content }}</textarea>
							
							@if ($errors->has('post_content'))
	                            <span class="help-block">
	                                <strong>{{ $errors->first('post_content') }}</strong>
	                            </span>
	                        @endif
						</div>

						<div class="form-group">
							<input type="submit" class="btn btn-primary" value="Update" />
							<a class="btn btn-primary" href="{{ route('pages.index') }}">Cancel</a>
						</div>
					</form> 

				</div>
			</div>

		@endif

	</div>
	
@endsection

show.blade.php


@extends('main')

@section('title', '| Page')

@section('content')
		
	<div class="container">
		
		{{-- Check if current user is logged-in or a guest --}}
		@if (Auth::guest())
			
			<p class="mt-5">Cheatn?, please <a href="/login/">login</a> to continue.</p>
			
		@else
		
			<div class="blog-header">
		        <h1 class="blog-title">{{ $page->post_title }}</h1>
		        <p>{{ date('M j, Y', strtotime( $page->created_at )) }} <a href="{{ route('pages.edit', $page->id) }}">{Edit}</a></p>
		    </div>
			
			<div class="row">
				<div class="col-sm-12 blog-main">

					<div class="blog-content">
						{{-- Inserts HTML line breaks before all newlines in a string --}}
						{!! nl2br( $page->post_content ) !!}
					</div>

				</div>
			</div>
			
		@endif

	</div>
	
@endsection

That’s it happy coding ^_^

References and Credits

Modifying Columns

Advertisement