Yearly archives: 2019

User interface for display of Laravel Logfiles

I was having a lot of problems displaying log files in the admin area of my application.  The Logfiles were being written to following each transaction, and a typical daily log file would be 10MB.

The best available packages would crash and burn with this size of logfile.

I tried both rap2hpoutre/laravel-log-viewer and arcanedev/log-viewer



namespace App\Http\Controllers;

use Illuminate\Http\Request;
use SplFileInfo;
use File;

class LogsController extends Controller
    public $perPage = 500;

    public function index()

        $files = $this->getLogfiles();

        return view('logs.index')->withFiles($files)->withLog([]);

    public function show(Request $request, $index)
        $files = $this->getLogfiles();
        $log = collect(file($files[$index]->getPathname(), FILE_IGNORE_NEW_LINES));
        $page = intval($request->get('page',1));
        $paginator['page'] = $page;
        $paginator['total'] = intval(floor($log->count() / $this->perPage))+1;

        $log=$log->slice(($page-1) * $this->perPage, $this->perPage);

        return view('logs.index')

    protected function getLogFiles()
        $directory = storage_path('logs');

        $logFiles = collect(File::allFiles($directory))
            ->sortByDesc(function (SplFileInfo $file) {
                return $file->getMTime();

        return $logFiles;


View (Bootstrap 4 flavour)


<div class="container-fluid">

    <h5 class="pt-3">Logs</h5 class="pt-3">

    <div class='row'>
        <div class='col-md-2'>
            <ul class='list-group'>
                @foreach($files as $key => $file)
                    <li class='list-group-item'><a href="{{ route('',$key) }}">{{ $file->getFilename() }}</a></li>
        <div class='col-md-10'>
            <ul class="pagination">
                <li class="page-item @if($p['page']==1) active @endif"><a class="page-link" href="{{ route('',['index'=>$index, 'page'=>1]) }}">First</a></li>

                @if($p['page']-4 > 1) <li class="page-item disabled"><a class="page-link"  href="#">&hellip;</a></li>@endif
                @if($p['page']-3 > 1) <li class="page-item"><a class="page-link" href="{{ route('',['index'=>$index, 'page'=>$p['page']-3]) }}">{{ $p['page']-3 }}</a></li>@endif
                @if($p['page']-2 > 1) <li class="page-item"><a class="page-link" href="{{ route('',['index'=>$index, 'page'=>$p['page']-2]) }}">{{ $p['page']-2 }}</a></li>@endif
                @if($p['page']-1 > 1) <li class="page-item"><a class="page-link" href="{{ route('',['index'=>$index, 'page'=>$p['page']-1]) }}">{{ $p['page']-1 }}</a></li>@endif
                @if($p['page'] != 1 && $p['page'] != $p['total'] )
                    <li class="page-item active"><span class="page-link">{{ $p['page'] }}</span></li>

                @if($p['page']+1 < $p['total']) <li class="page-item"><a class="page-link" href="{{ route('',['index'=>$index, 'page'=>$p['page']+1]) }}">{{ $p['page']+1 }}</a></li>@endif
                @if($p['page']+2 < $p['total']) <li class="page-item"><a class="page-link" href="{{ route('',['index'=>$index, 'page'=>$p['page']+2]) }}">{{ $p['page']+2 }}</a></li>@endif
                @if($p['page']+3 < $p['total']) <li class="page-item"><a class="page-link" href="{{ route('',['index'=>$index, 'page'=>$p['page']+3]) }}">{{ $p['page']+3 }}</a></li>@endif
                @if($p['page']+4 < $p['total']) <li class="page-item disabled"><a class="page-link"  href="#">&hellip;</a></li>@endif

                    <li class="page-item @if($p['page'] == $p['total']) active @endif"><a class="page-link" href="{{ route('',['index'=>$index, 'page'=>$p['total']]) }}">Last</a></li>


            <ul class='list-group list-group'>
                @foreach($log as $logline)
                        <li class='list-group-item small 
                            @if(Illuminate\Support\Str::contains($logline, '.CRITICAL:')) list-group-item-danger @endif
                            @if(Illuminate\Support\Str::contains($logline, '.ERROR:')) list-group-item-warning @endif
                            'style="padding: 0.25rem 1.25rem;">{{ $logline }}</li>




Route::get('/logs', 'LogsController@index')->name('logs');
Route::get('/logs/{index}', 'LogsController@show')->name('');

Preferably wrapped in Auth Middleware

Thats it.  Just add /logs to your navigation

Using Spatie Valuestore to hold frequently used settings

This was a reply posted to the Laracasts forum.  I know I will use this in the future, so documented here also as a reminder to myself as much as anything.

Install Valuestore composer require spatie/valuestore

In AppServiceProvider register method;

  public function register()
    $this->app->singleton('valuestore', function () {
      return \Spatie\Valuestore\Valuestore::make(storage_path('app/settings.json'));

    $values = $this->app->valuestore->all();

    $this->app->bind('settings', function () use($values) {
      return $values;

What we have in the app container is a singleton that points to the valuestore class.  When you use that, you are directly interacting with the settings stored in the file.

When you use the settings bound to the app container, you are using a cached version of the values as they were at the start of the request cycle (as an associated array).

So instead of writing the current Euro rate to a database row, put it in the valuestore instead;

app('valuestore')->put('EUR', $rate)

and in your model when you want to apply this;

public function getPriceEUR()
  return intval($this->usd_price / app('settings')['EUR'] * 100);}

By using settings and not valuestore the file will only be accessed once and not for each iterated product in a collection.

Of course you now have a place where you can store other currencies or any other application settings using the full features of the Valuestore package.

Using Laravel Polymorphic relationships for different user profiles

Laravel Eloquent polymorphic relations are similar to standard relationships, except that the model on one side of the relationship is defined by a column in the database table. Typically this would allow a single ‘child’ model to be attached to multiple different parents, for example, a Comment model can belong to a Post or a Page. An Image model can belong equally to an Item or a Category.  In this example we are going to reverse this typical arrangement and have the User model belong to different profile types.

Imagine a belongsTo relationship where in a table contains a foreign key to the ID of the other model, a polymorphic relationship uses an additional column to specify the model also.

In this example, we will be able to create tables (and models) that contain profile information for different types of users. The Admin user has one set of attributes and a Customer has a totally different set of attributes. Both types still use the User model for identification and access to our application.


Assuming a simple Laravel installation, where php artisan make:authhas been used to create a basic authentication solution.

We can add an AdminProfile and CustomerProfile

php artisan make:model AdminProfile -m
php artisan make:model CustomerProfile -m

(the -m will create migrations as well as the model)

In the migration files, add the attributes that are specific to that type of user


 Schema::create('customer_profiles', function (Blueprint $table) {

The only other database work to do is to add the polymorphic columns to the existing users table.  We can create a new migration to extend the users.

php artisan make:migration add_polymorphism_to_users --table=users
 Schema::table('users', function (Blueprint $table) {

A little work on the models so that they have the polymorphic relationship

User Model

Add to the existing user model;

 protected $with = ['profile'];
 public function profile()
   return $this->morphTo();

AdminProfile Model

<?php namespace App; 

use Illuminate\Database\Eloquent\Model; 

class AdminProfile extends Model 
  protected $guarded = [];
  public function user() 
    return $this->morphOne('App\User', 'profile');

CustomerProfile Model

<?php namespace App; 

use Illuminate\Database\Eloquent\Model; 

class CustomerProfile extends Model 
  protected $guarded = [];
  public function user() 
    return $this->morphOne('App\User', 'profile');

Run the migrations php artisan migrate

We can now have two different profile types associated with any user.  Two users have been created, and they have no profile associated with them at the moment.

Let’s test it with Tinker;
$profile = App\AdminProfile::create(['manager'=>'Donald','department'=>'Retail'])

We now have created a profile for our administrator user and attached it to their user account

$profile = App\CustomerProfile::create(['address1'=>'Lilac Cottage','address2'=>'Leeming Lane'])

And created a customer profile and attached this user 2

We can check the database and see the profile_type column has been populated

Thanks to the $withattribute added to the user model, whenever we get a user, we will also get the profile fields

>>> User::find(1)
=> App\User {#2962
 id: 1,
 name: "john doe",
 email: "",
 email_verified_at: null,
 created_at: "2019-01-19 13:00:23",
 updated_at: "2019-01-19 13:06:06",
 profile_type: "App\AdminProfile",
 profile_id: 1,
 profile: App\AdminProfile {#2972
   id: 1,
   department: "Retail",
   payroll: null,
   manager: "Donald",
   created_at: "2019-01-19 13:05:39",
   updated_at: "2019-01-19 13:05:39",
>>> User::find(2)
=> App\User {#2966
 id: 2,
 name: "jane smith",
 email: "",
 email_verified_at: null,
 created_at: "2019-01-19 13:00:54",
 updated_at: "2019-01-19 13:12:12",
 profile_type: "App\CustomerProfile",
 profile_id: 1,
 profile: App\CustomerProfile {#2980
   id: 1,
   address1: "Lilac Cottage",
   address2: "Leeming Lane",
   address_city: null,
   address_postcode: null,
   address_country: null,
   mobile: null,
   landline: null,
   created_at: "2019-01-19 13:12:02",
   updated_at: "2019-01-19 13:12:02",


To make it easy to know what type of user profile we are dealing with, we can extend the User model with a couple of accessors

  public function getHasAdminProfileAttribute()
    return $this->profile_type == 'App\AdminProfile';

  public function getHasCustomerProfileAttribute()
    return $this->profile_type == 'App\CustomerProfile';

>>> User::find(2)->hasAdminProfile
=> false
>>> User::find(2)->hasCustomerProfile
=> true