PHP
laravel
nova
laravel-admin
laravel-nova

Laravel Nova と laravel-admin を比較してみる

この記事について

Laravel のメイン開発者である Taylor Otwell さん謹製の、管理者用サイト(サブサイト)作成パッケージである Laravel Nova(以下 Nova)と、同様のツールで、以前から存在する laravel-admin を比較してみます。

その上で、有償(個人利用なら 99 USD、商用/チーム利用なら 199 USD) の Nova を導入するべきかどうか、という検討もしてみます。

期待も込めて、やや Nova 贔屓目で記載しますので、その点ご了承ください。

どちらも多機能なので、随時更新していきたいと思います。

Laravel Nova とは

Nova is a beautifully designed administration panel for Laravel.
Laravel Nova - Beautifully-designed administration panel for Laravel

OSS ではなく、サイトごとにライセンスを買う必要があります(メジャーバージョンごとに必要)。

こちらの記事に埋め込まれた動画で、詳しいデモを観ることができますので、お時間ある方はご覧ください。

Introducing Laravel Nova – Taylor Otwell – Medium

注意点として、Laravel 5.6 以上が必要です(5.5 が LTS なので、サポートしてほしかったな、というのが個人的な感想ですが、まぁそれはおいといて)。

laravel-admin とは

z-song/laravel-admin: Build a full-featured administrative interface in ten minutes

Nova 同様、管理者用インタフェースをまるっとつくってくれるパッケージです。

本記事執筆時点(2018-08-27)で 4,362 のスターがついています。

こちらは、Laravel 5.5 で動きます。

環境

  • Nova: 1.0.6
  • laravel-admin: 1.5.19
  • Laravel: 5.6.35

先に結論

以下、長くなりますので、私の到達した結論を先に述べておきます。

現時点では、 laravel-admin でいいのではないか、という印象です。

GitHub でイシュー報告を受け付けていますが、200 近いイシューが上がっています。
もうちょっと落ち着いてから見極めてもいいかんじがします。

https://github.com/laravel/nova-issues

ただ、執筆時点で毎日のようにパッチリリースが行われており、開発速度は遅くないようですし、いずれは laravel-admin を凌駕するパッケージになりうるポテンシャルは十分にあると感じているので、199ドル(商用ライセンス)は高くない、ということであれば、いまのうちに購入しても損はないかもしれません。

目次

  1. インストール方法
  2. インストール後に生成されるファイル
  3. 設定
  4. モデル(リソース)の追加
  5. 一覧ページ
  6. 編集ページ
  7. フィルター
  8. アクション
  9. その他の機能
  10. 総評

1. インストール方法

Nova

  1. Zip ダウンロードして解凍
  2. 導入したい Laravel アプリケーションのルートに解凍済みファイル群を配置
  3. composer.json を編集して composer update
  4. php artisan nova:install
  5. php artisan migrate

laravel-admin

  1. composer require
  2. php artisan vendor:publish
  3. php artisan admin:install

2. インストール後に生成されるファイル

Nova

app/Nova

Eloquent なモデルと対になる "Resource" と呼ばれる ViewModel 的なクラス群(インストール後には User.php が生成される)が配置されます。

Route や Controller は Nova の支配下にあり、Resource を増やしていくと自動的にメニューに現れます。

laravel-admin

app/Admin

こちらは Route と Controller を追加していく方式。

ただし、追加した Route と Controller を使えるようにするために、メニューへの追加は管理ページから手動で行います。

3. 設定

Nova の設定項目はまだ少ないですね。

Nova

  • ファイル: config/nova.php
  • 設定項目数(トップレベル): 4

laravel-admin

  • ファイル: config/admin.php
  • 設定項目数(トップレベル): 16

認証

Nova

カスタマイズ不可、メインアプリケーションのデフォルト guard が使われます(いずれカスタマイズできるようになりそうな気配はあります)。
ただし、アカウントのプロパティを用いてアクセス制御が可能です(デフォルトでは email で識別するように記述されている)。

laravel-admin

カスタマイズ可、デフォルトではインストール時に admin ガード(admin_users テーブル)が生成され、使われます。

4. リソース(モデル)の追加

メインアプリケーションに Post モデルを追加したとします。

Nova ではリソース、laravel-admin ではモデルと呼んでいる、テーブルと対になるクラスです。

Nova

Nova ではリソースを追加する方式です(ルーティングは自動で行われます)。

  1. コマンド実行

    php artisan nova:resource Post
    

image.png

メニュー項目は自動で追加されます(ラベルはカスタマイズ可)。

laravel-admin

laravel-admin ではルートおよびコントローラーを追加する方式です。

  1. コマンド実行

    php artisan admin:make UserController --model=App\\Post
    
  2. app/Admin/routes.php にリソース用のルートを追加

    app/Admin/routes.php
    @@ -12,4 +12,6 @@ Route::group([
    
     $router->get('/', 'HomeController@index');
    
    +    $router->resource('posts', 'PostController');
    +
     });
    
  3. サイドバーのメニューから、追加したルートをメニューへ追加

image.png

5. 一覧ページ

Nova

image.png

見た目はさほど laravel-admin と違いませんが、Nova ではリソースの取得は Ajax で行われています。

posts.author_id を Author に変換する方法は以下のとおりです。

App\Post に BelongsTo を返す author というメソッドが必要です。

// Text::make('author_id') の代わりに
BelongsTo::make('Author', 'author', User::class),

eager loading するための $with プロパティもあります。

Post.php
public static $with = [
    'author',
];

laravel-admin

image.png

posts.author_id を Author に変換する方法は以下のとおりです。

// $grid->author_id('Author ID') の代わりに
$grid->author_id('Author')->display(function ($id) {
    return User::find($id)->name;
});

6. 編集ページ

Nova

image.png

Nova では、リソース上で一度関連付けを行ってしまえば、他のページのために同様の関連付けを行う必要はありません(できません、といったほうが正確ですが)。

ドロップダウンリストの中身は Ajax で取得されます。

laravel-admin

image.png

laravel-admin では、一覧、詳細、編集、それぞれのページで関連付けを行う必要があります。

PostController.php
protected function form()
{
    // snip
    $form->select('author_id', 'Author')->options(function ($id) {
        $user = User::find($id);

        if ($user) {
            return [$user->id => $user->name];
        }
    });
    // snip
}

ドロップダウンリストの中身は、オプションの数が多ければ、Ajax で取得する方式にすることもできますが、API は自分で作成する必要があります。

7. フィルター

一覧ページにおいて、絞り込みを行う機能です。

posts.category というカラムを追加して、このカラムの値でフィルタリングできるようにするまでの手順を比較します。

Nova

$ php artisan nova:filter PostCategory

app/Nova/Filters 以下に PostCategory.php が生成されますので、処理を書きます。

PostCategory.php
<?php

namespace App\Nova\Filters;

use Illuminate\Http\Request;
use Laravel\Nova\Filters\Filter;

class PostCategory extends Filter
{
    public function apply(Request $request, $query, $value)
    {
        return $query->where('category', $value);
    }

    public function options(Request $request)
    {
        return [
            'post' => 'Post',
            'blog' => 'Blog',
        ];
    }
}

フィルターを登録します。

Post.php
public function filters(Request $request)
{
    return [
        new PostCategory,
    ];
}

image.png

もうひとつ、Nova には Lens という面白い機能がありまして、ここでは詳述しませんが、集計や他テーブルのカラムを組み合わせて自由にデータセットを抽出することができます。

興味ある方は以下のドキュメントをご覧ください。

Defining Lenses

laravel-admin

こちらは、フィルターの登録のみで済みます。

PostController.php
protected function grid()
{
    // snip
    $grid->filter(function ($filter) {
        $filter->equal('category')->select(['post' => 'Post', 'blog' => 'Blog']);
    });
    // snip
}

image.png

8. アクション

一覧ページにて、単一あるいは複数の行を選択して実行できる処理です。

ここでは、複数の投稿を選択して、公開日時をセットするアクションを追加してみます。

Nova

$ php artisan nova:action PublishAction

app/Actions 以下にファイルが生成されますので、処理を書きます。

PublishAction.php
public function handle(ActionFields $fields, Collection $models)
{
    $models->each(function ($model) {
        $model->published_at = Carbon::now();
        $model->save();
    });
}

image.png

キューを使って非同期に処理を行うこともできます。

laravel-admin

一方、laravel-admin では、アクションを実行する(APIを叩く) JavaScript を記述していくスタイルです。

app/Admin/Extensions/Tools 以下に PublishAction.php を作成し、以下のように書きます。

PublishAction.php
<?php

namespace App\Admin\Extensions\Tools;

use Encore\Admin\Grid\Tools\BatchAction;

class PublishAction extends BatchAction
{
    public function script()
    {
        return <<<EOT

$('{$this->getElementClass()}').on('click', function() {

    $.ajax({
        method: 'post',
        url: '{$this->resource}/publish',
        data: {
            _token:LA.token,
            ids: selectedRows(),
        },
        success: function () {
            $.pjax.reload('#pjax-container');
            toastr.success('published');
        }
    });
});

EOT;
    }
}

それを、PostController に組み込みます。

PostController.php
protected function grid()
{
    // snip
    $grid->tools(function ($tools) {
        $tools->batch(function ($batch) {
            $batch->add('Publish', new PublishAction());
        });
    });
    // snip
}

API 用のコントローラーもつくります。

PublishController.php
<?php

namespace App\Admin\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Post;
use Carbon\Carbon;

class PublishController extends Controller
{
    public function __invoke(Request $request)
    {
        foreach (Post::find($request->get('ids')) as $post) {
            $post->published_at = Carbon::now();
            $post->save();
        }
        return ['status' => 'ok'];
    }
}

ルーティングも追加する必要があります。

9. その他の機能

その他に、Nova で気になった機能を一部ご紹介します。ここまで見てきたとおり、データ管理、という最重要機能については、両者それほど決定的な違いがないとかんじていますが、その他の機能で、もしかしたらキラーフィーチャー的なのがあるかもしれませんので、もう少しお付き合いください。

9.1. Cards

Cards

Vue コンポーネントとそれと対になる PHP ファイルをパッケージとして作成し、下記のようになんらかの情報を含んだ「カード」を表示できるようにする仕組みです。

image.png

これがなかなか興味深く、フロントエンドとバックエンドがワンパックになっている Laravel ならではの発想というか、あーこういうやり方があるのかーと思わされた仕組み(少なくとも私はいままで見たことがありませんでした)なので、ライセンスを購入された方はぜひともカードを作成してみてください。

9.2. Metrics

Defining Metrics

ダッシュボードによるあるグラフやインジケータを出すやつです。

特徴は、カードの拡張として実装されており、フロントエンドの処理は書く必要がなく、メトリックスの種類ごとにある基底クラスを extends して、データ取得の処理を書くだけで、生成されます。

image.png
(画像は nova.laravel.com/docs より拝借)

laravel-admin では組み込みでは機能を提供しておらず、chartjs を使ってやってね、というガイダンスがあるのみです。

Custom chart - Laravel-admin

10. 総評

管理者用サイトという、とかく後回しになってしまいがち、実装もおざなりになりがち、コストもかけずに済ませたいと思われがち(注:個人の見解です)な機能群に対して、 199 USD / サイト、という費用をどう見るか、という点においては、先述したとおり、まだ laravel-admin でいいかもしれない、というのが現段階での私の印象ですが、jquery ベースの laravel-admin に対して、Vue.js ベースの Nova、とにかく実装コード量を少なく済ませようと配慮された(と、私は感じました)設計、OSS でなくとも、Otwell 氏が直接携わっているプロジェクト、と、将来性は間違いなくあると感じます。

私個人は、もし次のプロジェクトで管理者用サイトをイチからつくるなら、迷いなくライセンスを購入するつもりです。

試された方で、本記事にない Pros/Cons お持ちの方がいたら、ぜひコメント欄にて教えてください :bow: