
Create a new Livewire Component
Let's create a livewire component by making use of the "php artisan livewire:make" command. I'll let you name however you want it.
php artisan livewire:make Posts/Popular
CLASS: app/Http/Livewire/Posts/Popular.php VIEW: resources/views/livewire/posts/popular.blade.php
Define the Route
Now that we have the component, let's define a new route that will be used to access the popular posts component. It's also recommended that you provide the route name to easily reference the route and generate the link.
Route::get('/posts/popular', \App\Http\Livewire\Posts\Popular::class) ->name('posts.popular');
Component Class
The component class will contain the "logic to retrieve the popular posts" with a filter to select the "periods". We'll also be making use of Livewire computed properties to dynamically retrieve the post based on the selected duration.
public $selectedDuration = 7; public $periods = [ 1 => 'Today', 7 => 'Last 7 days', 14 => 'Last 14 days', 28 => 'Last 28 days', ];
Get Posts Computed Property
The computed property will retrieve all of the popular posts by the total number of views using "orderByViews" method. Do note that this method is provided by the eloquent viewable package. Now every time the "selectedDuration" property is updated, this computed property will get executed and perform the query to re-retrieve the post with the specified condition.
use CyrildeWit\EloquentViewable\Support\Period; public function getPostsProperty() { return Post::query() ->orderByViews('desc', Period::pastDays($this->selectedDuration)) ->get() ->toArray(); }
Complete Example
The complete code example should be as follows.
<?php namespace App\Http\Livewire\Posts; use App\Models\Post; use Livewire\Component; use CyrildeWit\EloquentViewable\Support\Period; class Popular extends Component { public $selectedDuration = 7; public $periods = [ 1 => 'Today', 7 => 'Last 7 days', 14 => 'Last 14 days', 28 => 'Last 28 days', ]; public function getPostsProperty() { return Post::query() ->orderByViews('desc', Period::pastDays($this->selectedDuration)) ->get() ->toArray(); } public function render() { return view('livewire.posts.popular'); } }
The Views
For the blade views, it will be located inside the "livewire.posts.popular" directory. The page structure for this should be quite generic depending on how you style the page so the code example below will just show the logic of the implementation.
The select will contain the "periods" and it will be making use of "wire:model" to sync with the "selectedDuration" value. So anytime the option is chosen from the select, the value of the "selectedDuration" will be updated.
<select wire:model="selectedDuration"> @foreach($periods as $duration => $period) <option value="{{ $duration }}"> {{ $period }} </option> @endforeach </select>
@foreach($this->posts as $post) <div class="card"> <h1>{{ $post->title }}</h1> </div> @endforeach