Laravel Nova Cheat Sheet

Background

Laravel Nova  is one of the most powerful web development toolkits if you’re a Website or PHP/Laravel developer. For a rock bottom price you can save years in development time by simply purchasing this software. At Vander Host, many of our back-end systems are created using Laravel and Nova. As such, we need a quick way to bootstrap new applications and this article is just what we need to get into the hyperlane.

  • Updated 07 Nov 2021 to include boilerplate installation and composer require commands
  • Updated 13 Apr 2023 to include a table of contents and information on responsive mode and breadcrumbs updated

Installation with Jetstream

I love Jetstream but you can simply leave out --jet below to install Laravel Nova without it:

laravel new project-name --jet
cd project-name

Mail Testing – Adding Helo

mc -e .env, add database, fix email sending to be Helo compatible

MAIL_HOST=localhost
MAIL_USERNAME="Voice-Commander"
MAIL_FROM_ADDRESS="[email protected]"

We install Nova via composer since we have a license and this method allows auto updating.

composer config repositories.nova '{"type": "composer", "url": "https://nova.laravel.com"}' --file composer.json

Then update composer.json

Be sure to replace ~4.0 with the correct value, e.g. ~4.0, ~3.0  or 4.22.2

"require": {
    "php": "^7.2.5",
    "fideloper/proxy": "^4.2",
    "laravel/framework": "^7.0",
    "laravel/nova": "~4.0"
},
composer update --prefer-dist
php artisan nova:install
php artisan migrate

Add this to .env

NOVA_LICENSE_KEY=

Let the games begin!

Debugging

You need Ray.

composer require spatie/laravel-ray

Adding Breadcrumbs & Responsive Theme

This section used to speak about adding breadcrumbs and adding a responsive theme, but this is now all included!

See the Laravel Nova release notes from November 2022 where the announcement about breadcrumbs is made:
https://nova.laravel.com/releases/4.19.0

Sorting Menu Items

The manual has a good example for this.

Adding the Ability to Customize the Default Sort Order

The Laravel Nova guys haven’t added any specific documentation on how to do the default sort order for resources. They probably did this because they assume a certain level of proficiency when working with Laravel Nova. Personally I think this is a shame but to assist the community here is the standard copy/paste job I use. In Nova/Resource.php:

Add a new static $sort variable and replace indexQuery:

/**
* Default ordering for our custom index query.
*
* @var array
*/

public static $sort = ['id' => 'desc'];

/**
* Custom index query that allows easy sorting of individual
* resources by simply adding a public static $sort option
*/

public static function indexQuery(NovaRequest$request, $query)
{
   if (empty($request->get('orderBy'))) {
      $query->getQuery()->orders = [];
      return $query->orderBy(key(static::$sort), reset(static::$sort));
   }

   return $query;
}

Then in your individual resources, do something this:

public static $sort = ['name' => 'asc'];

Better Sticky and Detachable Filters

This package gives you super flexibility and a filter of which the state can be saved!

https://github.com/outl1ne/nova-detached-filters/

Be sure to also check out this section of the manual about instant filters:

https://nova.laravel.com/docs/4.0/resources/fields.html#filterable-fields

Creating a Boolean Filter

The default documentation for boolean filters for Laravel Nova 4 is here, but actually to create a simple true/false/checkbox filters one should rather use the select filter (the default type). Here is an example:

php artisan nova:filter MigratedFilter

Then this source code:

public function apply(NovaRequest $request, $query, $value)
{
   return$query->where('migrated', $value);
}

public function options(NovaRequest $request)
{
   return [
      'Yes' => true,
      'No' => false,
   ];
}

Add the filter to your resource. We’re using the Nova Detached Filter package, which will mean you end up with three extra methods for filters (but it’s worth it):

public function cards(Request $request)
{
   return [
      (new NovaDetachedFilters($this->myFilters()))
      ->persistFilters()
      ->withToggle()
      ->width('full'),
   ];
}

public function filters(Request$request)
{
   return $this->myFilters();
}

protected function myFilters()
{
   return [
      new MigratedFilter(),
   ];
}

A select filter with distinct fields

To quickly add a select dropdown filter based on distinct text fields, do this:

public function apply(NovaRequest $request, $query, $value)
{
   return $query->whereDnsProvider($value);
}

public function options(NovaRequest $request)
{
   $uniqueList = Domain::select('dns_provider')
      ->distinct()
      ->get()
      ->pluck('registrar')
      ->toArray();
   
   return array_combine($uniqueList, $uniqueList);
}

Notes Field

Adding notes to a database record is often a requirement. I highly recommend Outl1ne’s notes package:
https://github.com/outl1ne/nova-notes-field

composer require outl1ne/nova-notes-field
php artisan migrate

Now add it to your code:

NotesField::make('Notes'),

Impersonation

Laravel Nova 4 has built in impersonation, but it’s not very easy to use and too much customization is required to get it working properly.

Instead we prefer George’s module:
https://github.com/KABBOUCHI/nova-impersonate

composer require kabbouchi/nova-impersonate
php artisan vendor:publish --tag=nova-impersonate-config
php artisan vendor:publish --tag=nova-impersonate-views
To use, add this to the default User.php resource in /Nova 
use KABBOUCHI\NovaImpersonate\Impersonate;

Impersonate::make($this),

Disable the ‘i’ key_down shortcut in config/ because otherwise random ‘i’ key presses will impersonate.

Jetstream compatibility issues

Please just be aware that you might have compatibility issues if you’re also using Jetstream. Basically going into and out of impersonation doesn’t always work and you have to log on again. This is a pretty complicated issue. See here:

https://github.com/KABBOUCHI/nova-impersonate/issues/101

Timezone/Locale/Currency

In config/app.php change timezone and locale

In config/nova.php change path and currency

php artisan nova:user

Models with Migrations

Create a model but at the same time also create a migration:

php artisan make:model Command -m

Hide Resource from Navigation

public static $displayInNavigation = false;

ENUMs Part 1

Create your first ENUM to keep your code nice and consistent.

To keep databases values consistent (and in lowercase), but still have a refactorable UI, one can use ENUMs.

<?php

namespace App\Enums;

class CommandStatus
{
   const NEW = "new";
   const IDEA = "idea";
   const DRAFT = "draft";
   const PRODUCTION = "production";
   
   public static function uiOptions()
   {
      return [
         self::NEW => 'New',
         self::IDEA => 'Idea',
         self::DRAFT => 'Draft',
         self::PRODUCTION => 'Production',
      ];
   }
}

Expand your users table with these two fields:

$table->string('api_token')->nullable();
$table->boolean('admin')->false();

You’ll need a factory to create model examples and for testing. Have a look at the UserFactory, but here’s the command:

php artisan make:factory CommandFactory -m Command

Here’s an example of a custom Seeder (here’s the docs). Here’s the inside:

protected $model = Command::class;

public function definition()
{
   return [
      'name' => $this->faker->name,
   ];
}

Here’s a nice way of calling related records:

Category::factory(3)
->has(Command::factory()->count(3))
->create();

George Kabbouchi’s Logs Tool (a log file)

George is an incredibly talented programmer and we use his logs tool for troubleshooting:

composer require kabbouchi/nova-logs-tool

In NovaServiceProvider.php, tools():

new \KABBOUCHI\LogsTool\LogsTool(),

Publish the assets:

php artisan vendor:publish --provider="KABBOUCHI\LogsTool\LogsToolServiceProvider"

Edit config/nova-logs-tools.php and specify 25 as the default length.

Quickly adding related records

Use the one liner below with BelongsTo to quickly create a related record:

BelongsTo::make('Lead Source')
->showCreateRelationButton(),

Defaulting to a smaller font size

Design wise the default font for tables is a bit big so you probably want to compact table styles / columns by default. In the base resource (Nova/Resource.php) class:

public static $tableStyle = 'tight';

Change Per Page Output Options

This code snippet is useful if you don’t like how many records are displayed per page, for both the index page and for related pages:
public static $perPageOptions = [150, 250, 500, 1000];

public static $perPageViaRelationship = 50;

Standard Removals

Removing the header and footer and help cards.

Remove Help

Remove new Help, in /Nova/Dashboards/Main.php

Remove Footer

NovaServiceProvider.php, boot method:
Nova::footer(function ($request) {
   return Blade::render('');
});

You probably want to clear the logo too. Nova 4 has made this super complicated. The config is in nova.php, but try clearing it, it’s near impossible. They force you to use the logo and make you google to death to get rid of it. You could put an unknown file name in die resource, but it will give a console error.

Using ENUMs to display labels on Select boxes

We use the method below to output ENUMs using an uiOptions() static method:
Select::make('Status')
->options(CommandStatus::uiOptions())
->displayUsingLabels(),
And if you want something pretty:
Badge::make('Status')->map([
   'production' => 'success',
   'draft' => 'info',
   'idea' => 'warning',
   'new' => 'danger',
])->sortable(),

Adding Notes to Fields

Here’s the coolest notes plugin. Please note have you have to publish migration for Multi Tenancy.
composer require outl1ne/nova-notes-field
php artisan migrate
php artisan vendor:publish --provider="Outl1ne\NovaNotesField\NotesFieldServiceProvider" --tag="config"
To use it on Model, add use HasNotes and in resource NotesField
Don’t like the default alphabetical ordering of resources? Read this or do this:
In NovaServiceProvider register() function
public function register()
    {
        Nova::sortResourcesBy(function ($resource) {
            return $resource::$priority ?? 99999;
        });
    }
In resource:
public static $priority = 1;
If you don’t want the “With Trashed”
->withoutTrashed()

Old Article with Descriptions

Here are some of our favourite Laravel packages for bootstrapping successful projects:

Share this article

Leave a Reply

Your email address will not be published. Required fields are marked *

Scroll to Top