WordPress-Like Blog Laravel 5.7 and AdminLTE 3 (11) – Create a New Post
In this eleventh part of creating WordPress-Like Blog using Laravel 5.7 and AdminLTE 3, we will :
- Create Form to Add a New Post
- Create Form Validation
- Image Upload
- Create Image Thumbnail
Create Form to Add a New Post
We will install laravelcollective to make our job to create form easier. Open terminal and install laravelcollective :
1 |
composer require laravelcollective/html |
When the installation has finished, open config/app.php and add to ‘Provider’ and ‘Aliases’ part :
1 2 3 4 5 6 |
Collective\Html\HtmlServiceProvider::class, and 'Form' => Collective\Html\FormFacade::class, 'Html' => Collective\Html\HtmlFacade::class, |
Ok now we’re good to go.
Open Backend\BlogController.php and perform modification to create() method :
1 2 3 4 |
public function create(Post $post) { return view("backend.blog.create", compact('post')); } |
Create a new file, ‘create.blade.php’ inside resources/views/backend/blog directory :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
@extends('layouts.backend.main') @section('title', 'Laravel 5 Blog | Add New POst') @section('content') <div class="content-wrapper"> <!-- Content Header (Page header) --> <div class="content-header"> <div class="container-fluid"> <div class="row mb-2"> <div class="col-sm-6"> <h1 class="m-0 text-dark">Blog <small style="font-size: 15px">Add New Posts</small></h1> </div><!-- /.col --> <div class="col-sm-6"> <ol class="breadcrumb float-sm-right"> <li class="breadcrumb-item"><a href="{{ url('/home') }}"><i class="fa fa-dashboard"></i> Dashboard</a></li> <li class="breadcrumb-item"><a href="{{ url('/blog.index') }}">Blog</a></li> <li class="breadcrumb-item active">Add new</li> </ol> </div><!-- /.col --> </div><!-- /.row --> </div><!-- /.container-fluid --> </div> <!-- /.content-header --> <!-- Main content --> <section class="content"> <div class="container-fluid"> <div class="row"> <div class="col-md-12"> <div class="card"> <!-- /.card-header --> <div class="card-header"> <h3 class="card-title">Add New Post</h3> <div class="card-tools"> <div class="input-group input-group-sm" style="width: 150px;"> <input type="text" name="table_search" class="form-control float-right" placeholder="Search"> <div class="input-group-append"> <button type="submit" class="btn btn-default"><i class="fa fa-search"></i></button> </div> </div> </div> </div> <!-- /.card-header --> <div class="card-body p-1"> {!! Form::model($post, [ 'method' => 'POST', 'route' => 'backend.blog.store', ])!!} <div class="form-group {{ $errors->has('title') ? 'has-error' : ''}}"> {!! Form::label('title') !!} {!! Form::text('title', null, ['class'=>'form-control']) !!} @if($errors->has('title')) <span class="badge badge-danger">{{ $errors->first('title') }}</span> @endif </div> <div class="form-group {{ $errors->has('slug') ? 'has-error' : ''}}"> {!! Form::label('slug') !!} {!! Form::text('slug', null, ['class'=>'form-control']) !!} @if($errors->has('slug')) <span class="badge badge-danger">{{ $errors->first('slug') }}</span> @endif </div> <div class="form-group {{ $errors->has('excerpt') ? 'has-error' : ''}}"> {!! Form::label('excerpt') !!} {!! Form::textarea('excerpt', null, ['class'=>'form-control']) !!} @if($errors->has('excerpt')) <span class="badge badge-danger">{{ $errors->first('excerpt') }}</span> @endif </div> <div class="form-group {{ $errors->has('body') ? 'has-error' : ''}}"> {!! Form::label('body') !!} {!! Form::textarea('body', null, ['class'=>'form-control']) !!} @if($errors->has('body')) <span class="badge badge-danger">{{ $errors->first('body') }}</span> @endif </div> <div class="form-group {{ $errors->has('published_at') ? 'has-error' : ''}}"> {!! Form::label('published_at', 'Publish Date') !!} {!! Form::text('published_at', null, ['class'=>'form-control','placeholder' => 'Date Format: Y-m-d H:i:s']) !!} @if($errors->has('published_at')) <span class="badge badge-danger">{{ $errors->first('published_at') }}</span> @endif </div> <div class="form-group {{ $errors->has('category_id') ? 'has-error' : ''}}"> {!! Form::label('category_id', 'Category') !!} {!! Form::select('category_id', App\Category::pluck('title','id'), null, ['class'=>'form-control', 'placeholder' => 'Select Category']) !!} @if($errors->has('category_id')) <span class="badge badge-danger">{{ $errors->first('category_id') }}</span> @endif </div> <div class="form-group {{ $errors->has('image') ? 'has-error' : ''}}"> {!! Form::label('image', 'Featured Image') !!} <br> {!! Form::file('image') !!} @if($errors->has('image')) <span class="badge badge-danger">{{ $errors->first('image') }}</span> @endif </div> <hr> {!! Form::submit('Create New Post', ['class' => 'btn btn-primary']) !!} {!! Form::close() !!} </div> <div class="card-footer clearfix"> </div> </div> <!-- /.card --> </div> </div> <!-- /.row --> </div><!-- /.container-fluid --> </section> <!-- /.content --> </div> <!-- /.content-wrapper --> @endsection @section('script') <script type="text/javascript"> $('#pagination').addClass('no-margin pagination-sm'); </script> @endsection |
Open the backend project url, and click Add New Post on the sidebar menu :
Create Form Validation
Now we will create a validation rule before the form is submitted. For example, which field that required to be filled with data, the correct format date, etc. Let’s begin by adding some code to Backend\BlogController.php store() method :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
public function store(Requests\PostRequest $request) { $data = $this->handleRequest($request); $request->user()->posts()->create($data); return redirect(route('backend.blog.index'))->with('message', 'Post has been added'); } private function handleRequest($request){ $data = $request->all(); if($request->hasFile('image')){ $image = $request->file('image'); $fileName = $image->getClientOriginalName(); $destination = $this->uploadPath; $image->move($destination, $fileName); $data['image'] = $fileName; } return $data; } |
Here we also add handleRequest() method to cope with image upload that we will create later.
Create new request, the PostRequest by typing the command on the terminal :
1 |
php artisan make:request PostRequest |
Open the newly PostRequest.php inside app\Http\Requests folder. Change the authorize() method inside PostRequest to true, and add the rules method :
1 2 3 4 5 6 7 8 9 10 11 |
public function rules() { return [ 'title' => 'required', 'slug' => 'required|unique:posts', 'body' => 'required', 'published_at' => 'date_format:Y-m-d H:i:s', 'category_id' => 'required', // 'image' => 'mimes:jpg,jpeg,bmp,png', ]; } |
Don’t forget to add the namespace :
1 |
use App\Http\Requests; |
Try to Submit the form, error message will occured :
Before we submit the form with valid data, there is one step we need to do, that is to add $fillable property inside Post model :
1 |
protected $fillable = ['title','slug','excerpt','body','published_at','category_id','image']; |
And add a new method :
1 2 3 |
public function setPublishedAtAttribute($value){ $this->attributes['published_at'] = $value ? : NULL; } |
Image Upload
To upload an image, first we need to modify create.blade.php to tell the form multipart/form-data attribute :
1 2 3 4 5 |
{!! Form::model($post, [ 'method' => 'POST', 'route' => 'backend.blog.store', 'files' => TRUE, ])!!} |
Add new property uploadPath along with construct() method inside Backend\BlogController.php
1 2 3 4 5 6 7 |
protected $uploadPath; public function __construct() { parent::__construct(); $this->uploadPath = public_path(config('cms.image.directory')); } |
Add a new folder ‘img’ inside public folder.
Let’s try to fill the form with valid data and push Submit button.
Create Image Thumbnail
After we successfully add a post with image, now we will create the image thumbnail automatically everytime a post with image is being submitted. We need a third party package, the intervention/image package.
1 |
composer require intervention/image |
When installation has finished, open config/app.php and add the following lines to Providers and Aliases section respectively.
1 2 3 4 5 |
Intervention\Image\ImageServiceProvider::class, and 'Image' => Intervention\Image\Facades\Image::class, |
Then run the configuration from the terminal :
1 |
php artisan vendor:publish --provider="Intervention\Image\ImageServiceProviderLaravel5" |
Next, modify the handleRequest() method inside Backend\BlogController :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
use Intervention\Image\Facades\Image; private function handleRequest($request){ $data = $request->all(); if($request->hasFile('image')){ $image = $request->file('image'); $thumbnail = $fileName = $image->getClientOriginalName(); $destination = $this->uploadPath; $uploaded = $image->move($destination, $fileName); if($uploaded){ $width = config('cms.image.thumbnail.width'); $height = config('cms.image.thumbnail.height'); $extension = $image->getClientOriginalExtension(); $thumbnail = str_replace(".{$extension}", "_thumb.{$extension}", $fileName); Image::make($destination . '/' . $fileName) ->resize($width,$height) ->save($destination . '/' . $thumbnail); } $data['image'] = $fileName; } return $data; } |
Create new config file, cms.php inside config folder :
1 2 3 4 5 6 7 8 9 10 11 |
<?php return [ 'image' => [ 'directory' => 'img', 'thumbnail' => [ 'width' => 250, 'height' => 170 ] ] ]; |
Modify these two methods on Post.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
public function getImageUrlAttribute($value){ $imageUrl = ""; if(!is_null($this->image)){ $directory = config('cms.image.directory'); $imagePath = public_path(). "/{$directory}/". $this->image; if(file_exists($imagePath)) $imageUrl = asset("{$directory}/" .$this->image); } return $imageUrl; } public function getImageThumbUrlAttribute($value){ $imageUrl = ""; if(!is_null($this->image)){ $directory = config('cms.image.directory'); $ext = substr(strrchr($this->image, '.'), 1); $thumbnail = str_replace(".{$ext}", "_thumb.{$ext}", $this->image); $imagePath = public_path() . "/{$directory}/" . $thumbnail; if(file_exists($imagePath)) $imageUrl = asset("{$directory}/" . $thumbnail); $imageUrl = $this->image; }else{ $imageUrl = ""; } return $imageUrl; } |
Hope this one doesn’t too long enough.
Github Commit.