Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

vainway 's avatar

Attach() method for multi inserts

Hello guys I want to attach 3 different tables ( skills, countries, timezone) in one post, First I was attaching(skills) only one table and making a post without a problem but when I added (countries & timezone) am getting an error BadMethodCallException Call to undefined method Illuminate\Database\Eloquent\Relations\BelongsToMany::countries()

<?php

namespace App\Http\Livewire;

use Livewire\Component;
use Livewire\WithFileUploads;
use App\Models\Skill;
use App\Models\Country;
use App\Models\TimeZone;
use App\Models\Post;
use Illuminate\Support\Facades\Auth;

class Post extends Component
{
    use WithFileUploads;

    public $title;
    public $uploadedFiles;
    public $selectedSkills = [];
    public $selectedCountries = [];
    public $selectedTimeZones = [];

    protected function rules ()
    {
        return [
            'title' => 'required|min:3',
            'uploadedFiles' => 'required|file|mimes:png,jpg,pdf|max:5120',
            'selectedSkills' => 'required|array|max:6',
			'selectedCountries' => 'required|array|max:6',
			'selectedTimeZones' => 'required|array|max:6',
        ];
    }
public function render()
    {
        $this->skills = Skill::all();
        $this->countries = Country::all();
        $this->zones = TimeZone::all();
        return view('livewire.post', [
            'skills' => $this->skills,
            'countries' => $this->countries,
            'zones' => $this->zones,
        ]);
    }

public function Post ()
    {
        $this->validate();

        $path = $this->uploadedFiles->store('public/storage/Posted');

        
		$post =   Post::create([
            'title' => $this->title,
            'uploadedFiles' => $path,
            'user_id' => Auth::user()->id
        ]);
		$post->skills()->attach($this->selectedSkills);
        $post->countries()->attach($this->selectedCountries);
        $post->zones()->attach($this->selectedTimeZones);

        return redirect()->back()->with('success', 'posted Successful');

    }

Skill.php // Model

public function post()
    {
        return $this->belongsToMany(Post::class, 'post_skill', 'post_id', 'skill_id');
    }

Post.php // Model

public function skills()
    {
        return $this->belongsToMany(Skill::class, 'post_skill', 'post_id', 'skill_id');
    }

    public function countries()
    {
        return $this->belongsToMany(Country::class, 'post_countries', 'post_id', 'country_id');
    }

    public function zones()
    {
        return $this->belongsToMany(TimeZone::class, 'post_zones', 'post_id', 'zone_id');
    }

Country.php // Model

public function post()
    {
        return $this->hasMany(Post::class, 'post_countries', 'post_id', 'country_id');
    }

TimeZone.php // Model

public function post()
    {
        return $this->hasMany(Post::class, 'post_zones', 'post_id', 'zone_id');
    }

post.blade.php

		<div class="row">
                <div class="col-md-12">
                    <div class="form-group">
                        <label class="bmd-label-floating">Skills required for your project?</label>
                        <div wire:ignore class="bootstrap-tagsinput info-badge">
                            <select wire:model.defer="selectedSkills" class="form-control js-select2-multi" data-placeholder="Enter Skills here..." multiple>                            
                                @foreach($skills as $skill)
                                    <option value="{{ $skill->id }}">{{ $skill->name }}</option>
                                @endforeach
                            </select>
                        </div>
                    </div>
                </div>
            </div>
						<div class="form-group mt-4">
                            <label class="bmd-label-floating">Add The Location you prefer:</label>
                            <div wire:ignore>
                                <select wire:model.defer="selectedCountries" class="form-control js-select2-country" data-placeholder="Add The Location here..." multiple>
                                    @foreach($countries as $country)
                                        <option value="{{ $country->id }}">{{ $country->name }}</option>
                                    @endforeach
                                </select>
                            </div>
                            @error('country')
                                <span class="invalid-feedback" role="alert" style="margin-left: 70px; margin-bottom: -10px">
                                    <strong>{{ $message }}</strong>
                                </span>
                            @enderror
                        </div>
			<div class="form-group mt-4">
                            <label class="bmd-label-floating">Choose your Time zone:</label>
                            <div wire:ignore>
                                <select wire:model.defer="selectedTimeZones" class="form-control js-select2-timezone" data-placeholder="Add Time zone here..." multiple>
                                    @foreach($zones as $zone)
                                        <option value="{{ $zone->id }}">{{ $zone->name }}</option>
                                    @endforeach
                                </select>
                            </div>
                            @error('TimeZone')
                                <span class="invalid-feedback" role="alert" style="margin-left: 70px; margin-bottom: -10px">
                                    <strong>{{ $message }}</strong>
                                </span>
                            @enderror
                        </div>

@section('scripts')

<script>
    $(document).ready(function () {
        $('.js-select2-multi').select2({
            closeOnSelect: false,
            maximumSelectionLength: 6,
            allowClear: true,
            minimumInputLength: 2,
            maximumInputLength: 20,
        });
        $('.js-select2-multi').on('change', function (e) {
            @this.set('selectedSkills', $(this).val()); 
        });
    });
</script>

<script>
    $(document).ready(function () {
        $('.js-select2-country').select2({
            closeOnSelect: false,
            maximumSelectionLength: 6,
            allowClear: true,
            minimumInputLength: 2,
            maximumInputLength: 20,
        });
        $('.js-select2-multi').on('change', function (e) {
            @this.set('selectedCountries', $(this).val()); 
        });
    });
</script>

<script>
    $(document).ready(function () {
        $('.js-select2-timezone').select2({
            closeOnSelect: false,
            maximumSelectionLength: 6,
            allowClear: true,
            minimumInputLength: 2,
            maximumInputLength: 20,
        });
        $('.js-select2-multi').on('change', function (e) {
            @this.set('selectedTimeZones', $(this).val()); 
        });
    });
</script>

@endsection
0 likes
6 replies
Sinnbeck's avatar

What line is throwing that error? This?

$post->countries()->attach($this->selectedCountries); 
vainway 's avatar

@Sinnbeck Yes, am making a post and it goes through but in the database am getting the same ids on both timezone and countries table as if I selected the same things on both tables

Sinnbeck's avatar

@vainway sorry I thought this was about the error?

Anyways. Use dd() on each item to see what data you are getting

vainway 's avatar

@Sinnbeck so, are you seeing any typos or errors I made I can change to make the post go through well

$post->skills()->attach($this->selectedSkills);
        $post->countries()->attach($this->selectedCountries);
        $post->zones()->attach($this->selectedTimeZones);

Is there a better way than this one because I was making a post well before adding $post->countries()->attach($this->selectedCountries); $post->zones()->attach($this->selectedTimeZones);

mlewis's avatar

I'm not sure this isn't because you have named the Livewire component the same as your Eloquent model.

Could you humour me for a moment and change your use statement to

use App\Models\Post as PostModel;

then change your post creation to

$post =   PostModel::create([
            'title' => $this->title,
            'uploadedFiles' => $path,
            'user_id' => Auth::user()->id
        ]);

And see if that works.

Please or to participate in this conversation.