laraveleloquentmany-to-manyeloquent-relationship

Laravel Many-To-Many Relationship working and fetching correct data, but shows "null" on access


in my Laravel application, I have many to many relationships with 2 tables, ls_blogs & ls_blog_categories, with the ls_blog_category_ls_blog table as a pivot, here is the code for better context
ls_blogs migration:

Schema::create('ls_blogs', function (Blueprint $table) {
            $table->id();
            $table->string('title');
 ..Other fields.

ls_blog_categories migration:

if (!Schema::hasTable('ls_blog_categories')) {
            Schema::create('ls_blog_categories', function (Blueprint $table) {
                $table->id();
                $table->string('name');
                $table->boolean('active')->default(false);
                $table->timestamps();
            });
        }

Pivot

  Schema::create('ls_blog_category_ls_blog', function (Blueprint $table) {
            $table->id();
            $table->foreignId('ls_blog_id')->nullable()->constrained()->nullOnDelete();
            $table->foreignId('ls_blog_category_id')->nullable()->constrained()->nullOnDelete();
            $table->timestamps();
        });

LsBlog Model:

public function categories()
    {
        return $this->belongsToMany(LsBlogCategory::class, 'ls_blog_category_ls_blog', 'ls_blog_id', 'ls_blog_category_id')
            ->wherePivotNotNull('ls_blog_category_id')
            ->where('ls_blog_categories.active', true);
    }

LsBlogCategory Model

   public function blogs()
    {
        return $this->belongsToMany(LsBlog::class, 'ls_blog_category_ls_blog')
            ->wherePivotNotNull('ls_blog_id')
            ->where('ls_blogs.is_active', true);
    }

Livewire Component trying to access

    public function mount($id)
    {
        $this->blog = LsBlog::with('categories')->find($id);
        dd($this->blog, $this->blog->categories); 

Result: enter image description here


Solution

  • Try with this i fix it with adding the layout attribut to the Livewire component and it works fine : LsBlog Model :

    namespace App\Models;
    
    use Illuminate\Database\Eloquent\Factories\HasFactory;
    use Illuminate\Database\Eloquent\Model;
    
    class LsBlog extends Model
    {
        use HasFactory;
    
        protected $fillable = ['title'];
    
        public function categories()
        {
            return $this->belongsToMany(LsBlogCategory::class,'ls_blog_category_ls_blog');
        }
    }
    

    LsBlogCategory Model :

    namespace App\Models;
    
    use Illuminate\Database\Eloquent\Factories\HasFactory;
    use Illuminate\Database\Eloquent\Model;
    
    class LsBlogCategory extends Model
    {
        use HasFactory;
    
        protected $fillable = ['name', 'active'];
    
        public function blogs()
        {
            return $this->belongsToMany(LsBlog::class, 'ls_blog_category_ls_blog');
        }
    }
    

    lsblogs migration :

    return new class extends Migration
    {
        /**
         * Run the migrations.
         */
        public function up(): void
        {
            Schema::create('ls_blogs', function (Blueprint $table) {
                $table->id();
                $table->string('title');
                $table->timestamps();
            });
        }
    
        /**
         * Reverse the migrations.
         */
        public function down(): void
        {
            Schema::dropIfExists('ls_blogs');
        }
    };
    

    ls_blog_categories Migration :

    return new class extends Migration
    {
        /**
         * Run the migrations.
         */
        public function up(): void
        {
            Schema::create('ls_blog_categories', function (Blueprint $table) {
                $table->id();
                $table->string('name');
                $table->boolean('active')->default(false);
                $table->timestamps();
            });
        }
    
        /**
         * Reverse the migrations.
         */
        public function down(): void
        {
            Schema::dropIfExists('ls_blog_categories');
        }
    };
    

    ls_blog_category_ls_blog Migration :

    return new class extends Migration
    {
        /**
         * Run the migrations.
         */
        public function up(): void
        {
            Schema::create('ls_blog_category_ls_blog', function (Blueprint $table) {
                $table->id();
                $table->foreignId('ls_blog_category_id')->constrained('ls_blog_categories');
                $table->foreignId('ls_blog_id')->constrained('ls_blogs');
                $table->timestamps();
            });
        }
    
        /**
         * Reverse the migrations.
         */
        public function down(): void
        {
            Schema::dropIfExists('ls_blog_category_ls_blog');
        }
    };
    

    Livewire Component :

    namespace App\Livewire;
    
    use Livewire\Component;
    use App\Models\LsBlog;
    use Livewire\Attributes\Layout;
    
    #[Layout('layouts.app')]
    class BlogShow extends Component
    {
        public $blog;
    
        public function mount($id)
        {
            $this->blog = LsBlog::with('categories')->findOrFail($id);
        }
    
        public function render()
        {
            return view('livewire.blog-show');
        }
    }
    

    Livewire view :

    <div class="container">
        @if ($blog)
            <h1>{{ $blog->title }}</h1>
    
            <h3>Categories:</h3>
            <ul>
                @forelse ($blog->categories as $category)
                    <li>
                        {{ $category->name }}
                        <br> Created At: {{ $category->pivot->created_at }}
                        <br> Updated At: {{ $category->pivot->updated_at }}
                    </li>
                @empty
                    <li>No categories available.</li>
                @endforelse
            </ul>
        @else
            <p>Blog not found.</p>
        @endif
    </div>
    

    layout :

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>My Application</title>
    
        @livewireStyles
    </head>
    <body>
        {{ $slot }}
    
        @livewireScripts
    </body>
    </html>