I am working on a blogging application in Laravel 8.
In the FrontendController controller I have:
namespace App\Http\Controllers;
use App\Models\Settings;
use App\Models\ArticleCategory;
class FrontendController extends Controller
{
protected $site_settings;
protected $theme_directory;
protected $site_name;
protected $tagline;
protected $owner_name;
protected $article_categories;
public function __construct()
{
$this->site_settings = Settings::first();
$this->theme_directory = $this->site_settings['theme_directory'] ?? null;
$this->site_name = $this->site_settings['site_name'] ?? null;
$this->tagline = $this->site_settings['tagline'] ?? null;
$this->owner_name = $this->site_settings['owner_name'] ?? null;
// Article categories
$this->article_categories = ArticleCategory::all();
}
}
The ArticlesController controller extends the one above:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\ArticleCategory;
use App\Models\Article;
class ArticlesController extends FrontendController {
// Articles per page
protected $per_page = 12;
public function index(Request $request) {
// Search query
$qry = $request->input('search');
$articles = Article::where('title', 'like', '%' . $qry . '%')
->orWhere('short_description', 'like', '%' . $qry . '%')
->orWhere('content', 'like', '%' . $qry . '%')
->orderBy('id', 'desc')
->paginate($this->per_page);
// Search results count
if ($request->input('search')){
$article_count = Article::where('title', 'like', '%' . $qry . '%')
->orWhere('short_description', 'like', '%' . $qry . '%')
->orWhere('content', 'like', '%' . $qry . '%')
->count();
}
return view('themes/' . $this->theme_directory . '/templates/index',
[
'theme_directory' => $this->theme_directory,
'search_query' => $qry,
'site_name' => $this->site_name,
'tagline' => $this->tagline,
'owner_name' => $this->owner_name,
'categories' => $this->article_categories,
'articles' => $articles,
'article_count' => $article_count ?? null
]
);
}
public function category($category_id) {
$category = ArticleCategory::where('id', $category_id)->first();
$articles = Article::where('category_id', $category_id)->paginate($this->per_page);
return view('themes/' . $this->theme_directory . '/templates/index',
[
'theme_directory' => $this->theme_directory,
'site_name' => $this->site_name,
'tagline' => $this->tagline,
'owner_name' => $this->owner_name,
'categories' => $this->article_categories,
'category' => $category,
'articles' => $articles
]
);
}
public function show($slug) {
// Single article
$article = Article::where('slug', $slug)->first();
return view('themes/' . $this->theme_directory . '/templates/single',
[
'theme_directory' => $this->theme_directory,
'site_name' => $this->site_name,
'tagline' => $this->tagline,
'owner_name' => $this->owner_name,
'categories' => $this->article_categories,
'article' => $article
]
);
}
}
The posts list view (index.blade.php):
@extends('themes/' .$theme_directory . '/layout')
@section('content')
<!-- Page Header -->
<header class="masthead" style="background-image: url({{ asset('themes/' . $theme_directory . '/img/home-bg.jpg') }}">
<div class="overlay"></div>
<div class="container">
<div class="row">
<div class="col-lg-8 col-md-10 mx-auto">
<div class="site-heading">
<h1>{{ $site_name }}</h1>
<span class="subheading">
@if(isset($category))
{{ $category->name }}
@else
{{ $tagline }}
@endif
</span>
</div>
</div>
</div>
</div>
</header>
<div class="container">
<div class="row">
<div class="col-lg-8 col-md-10 mx-auto">
@if (isset($search_query))
<p class="mt-0 text-muted">We found {{ $article_count }} posts containing <span class="quote-inline">{{ $search_query }}</span>:</p>
@endif
@if (count($articles))
@foreach ($articles as $article)
<div class="post-preview">
<a href="{{ url('/show/' . $article->slug) }}">
<h2 class="post-title">
{{ $article->title }}
</h2>
<h3 class="post-subtitle">
{{ $article->short_description }}
</h3>
</a>
<p class="post-meta">Posted by
<a href="#">{{ $article->user->first_name }} {{ $article->user->last_name }}</a>
on {{ date('j F, Y', strtotime($article->created_at)) }}
</p>
</div>
<hr>
@endforeach
@endif
<!-- Pager -->
@if($articles->hasPages())
<div class="clearfix">
<ul class="pagination">
<li class="next">
<a class="btn btn-primary {{ $articles->withQueryString()->onFirstPage() ? 'disabled' : '' }}" href="{{ $articles->previousPageUrl() }}">← Newer Posts</a>
</li>
<li class="prev">
<a class="btn btn-primary {{ $articles->withQueryString()->onLastPage() ? 'disabled' : '' }}" href="{{ $articles->nextPageUrl() }}">Older Posts →</a>
</li>
</ul>
</div>
@endif
</div>
</div>
</div>
<hr>
@endsection
Questions
- What would be an optimal way to reduce code repetition in the two controllers?
- Are there any code optimisation opportunities?