Laravel Nova BelongsToMany Relationship as Checkbox

Store your pivot relation at checkbox at create/update view?

For checkbox i use fourstacks/nova-checkboxes

1. Install composer package

composer require fourstacks/nova-checkboxes

2. Create Migrations

ads table

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateAdsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('ads', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('ads');
    }
}

ad_tags table

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateAdTagsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('ad_tags', function (Blueprint $table) {
            $table->id();
            $table->json('name');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('ad_tags');
    }
}

ad_tag_pivot table

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateAdTagPivotTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('ad_tag_pivot', function (Blueprint $table) {
            $table->id();
            $table->integer('ad_id')->unsigned();
            $table->integer('tag_id')->unsigned();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('ad_tags');
    }
}

3. Create Models

Ad

<?php

namespace App\Ads;

use Illuminate\Database\Eloquent\Model;

class Ad extends Model
{
    protected $table = 'ads';

    public function tags()
    {
        return $this->belongsToMany(Tag::class, 'ad_tag_pivot', 'ad_id', 'tag_id'); //->orderBy('order');
    }
}

Tag

<?php

namespace App\Ads;

use Illuminate\Database\Eloquent\Model;

class Tag extends Model
{
    protected $table = 'ad_tags';
}

4. Add Field to Ad Resource

\Fourstacks\NovaCheckboxes\Checkboxes::make('Tags', 'selected_tags')
    ->options( TagModel::all()->pluck( 'name',  'id')->toArray() )
    ->columns(3),

5. Create AdObserver

php artisan make:observer AdObserver --model=Ad

6. Observe updating & retrieved methods

  • updating method to save
  • retrieved method to retrive selected
<?php
namespace App\Observers;

use App\Ads\Ad;

class AdObserver
{
    public function retrieved(Ad $ad)
    {
        $ad->selected_tags = $ad->tags->pluck('id')->toArray();
    }

    public function updating(Ad $ad)
    {
        if($ad->isDirty('selected_tags'))
        {
            $ad->tags()->sync($ad->selected_tags);
            unset($ad->selected_tags);
        }
    }
}

7. Add Observer to Nova Service Provider

<?php
namespace Laravel\Nova;

use App\Ads\Ad;
use App\Observers\AdObserver;

class NovaServiceProvider extends ServiceProvider
{    
    public function boot()
    {
        ...
        Nova::serving(function () {
            Ad::observe(AdObserver::class);
        });

Enjoy!

;