Adding and saving fields in a related belongsToMany table

All we need is an easy explanation of the problem, so here it is.

The tables category, category_description and descriptions are related:

public function descriptions(): BelongsToMany
{
    return $this->belongsToMany(Description::class);

}
public function categories(): BelongsTo {
    return $this->belongsTo(Category::class);
}

public function descriptions(): BelongsTo {
    return $this->belongsTo(Description::class);
}
public function descriptions(): BelongsToMany
    {
        return $this->belongsToMany(Category::class);

    }

in Model respectively. When saving or updating:

public function createOrUpdate(Category $category, Request $request)
    {
        $category->fill($request->get('category'))->save();

        $category->descriptions()->syncWithoutDetaching(
            $request->input('category.descriptions', [])
        );
    }

An error:

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'description' in 'field list' (SQL: insert into `category_description` (`category_id`, `description`, `description_id`, `is_active`, `meta-description`, `meta-h1`, `meta-keyword`, `meta-title`, `name`, `slug`) values (1, 41231231, 0, 1, 23, 124, 12, 12, 12333312, 74))

Perhaps I missed something somewhere, since there is not so much experience.

UPDATE:

a category can have multiple entries, but the description has only one parent. Rewrote — One To Many (Polymorphic):

public function descriptions()
    {
        return $this->morphMany(Description::class, 'descriptable');
    }
public function descriptable()
    {
        return $this->morphTo();
    }

There are no problems with saving 1 record, but how to update several records at the same time?

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

How about?

// Category Model.

use Illuminate\Database\Eloquent\Model;

class Category extends Model
{
    public function descriptions()
    {
        return $this->belongsToMany(Description::class)
            ->using(CategoryDescription::class);
    }
}
// Description Model.

use Illuminate\Database\Eloquent\Model;

class Description extends Model
{

    protected $fillable = [
        "name",
        "description",
        "meta-title",
        "meta-description",
        "meta-keyword",
        "meta-h1",
        "slug",
        "is_active",
    ];

    public function categories()
    {
        return $this->belongsToMany(Category::class)
            ->using(CategoryDescription::class);
    }
}
// Intermediate Model.

use Illuminate\Database\Eloquent\Relations\Pivot;

class CategoryDescription extends Pivot
{

    protected $table = "category_description";
    public $incrementing = true;

    public function category()
    {
        return $this->belongsTo(Category::class, "category_id", "id");
    }

    public function description()
    {
        return $this->belongsTo(Description::class, "description_id", "id");
    }
}
// createOrUpdate method.

public function createOrUpdate(Category $category, Request $request)
{
    $category->fill($request->get('category'))->save();

    $description = Description::create(
        Arr::collapse($request->input('category.descriptions', []))
    );

    $category->descriptions()->syncWithoutDetaching(
        $description->id
    );
}

Notes:

Much as this may work for you, I personally think that you don’t have a many-to-many relationship here. I believe a one-to-many relationship is sufficient.

Method 2

The problem is you send data to be inserted in columns that are not found

You should send only the data that you need to insert in the table

so in your case, you should write your function as

$category->descriptions()->syncWithoutDetaching($description_id); // the id of the description you want to attach with this category

If you still don’t have the description yet in the database and you are creating it with the same request you can do something like this

Description::create(['columnName'=>$request->get('columnName'),'columnName2'=>$request->get('columnName2')])->id

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply