简体   繁体   中英

Add multiple categories for articles

I need to add several categories for a new article. I will write down everything I do in order:

migration of categories

public function up()
    {
        Schema::create('blog_categories', function (Blueprint $table) {
            $table->BigIncrements('id');
            $table->string('title', 128);
            $table->timestamps();
        });
    }

migration of articles

public function up()
    {
        Schema::create('articles', function (Blueprint $table) {
            $table->BigIncrements('id');
            $table->string('title', 128);
            $table->string('slug', 64);
            $table->string('subtitle', 256)->nullable();
            $table->timestamps();
        });
    }

creating another migration article_blog_category_table

public function up()
    {
        Schema::create('article_blog_category', function (Blueprint $table) {
            $table->unsignedBigInteger('blog_category_id')->nullable();
            $table->foreign('blog_category_id')
                ->references('id')->on('blog_categories')->onDelete('set null');
            $table->unsignedBigInteger('article_id')->nullable();
            $table->foreign('article_id')
                ->references('id')->on('articles')->onDelete('cascade');
        });
    }

Doing belongsToMany in models

article model

public function blog_categories()
    {
        return $this->belongsToMany('App\Models\BlogCategory');
    }

category model

public function articles()
    {
        return $this->belongsToMany('App\Models\Article');
    }
}

Next, I write the function for adding an article in the controller (I think there is no need to write the function for adding a category, everything is clear there)

Articles controller

public static function saveArticle(Request $request) {
        $validator = Validator::make($request->all(), [
            'blog_category_id' => 'required|numeric',
            'title' => 'required|max:128',
            'slug' => 'required|unique:articles|max:64',
            'subtitle' => 'max:256',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'message' => $validator->errors()->first()
            ], 422);
        }

        $article = new Article();

        $blog_category = BlogCategory::where('id', $request->blog_category_id)->first();

        if(!$blog_category){
            return response()->json([
                'message' => 'Blog category not found'
                ], 404);
        }

        $article->blog_category_id = $request->blog_category_id;
        $article->title = $request->title;
        $article->slug = $request->slug;
        $article->subtitle = $request->subtitle;

        $article->save();

        return Article::where('slug', $article->slug)->first();
    }

I have a method in the function to add one category. The question of how to add here so that you can add several categories, I cannot figure it out. You need something like $article->blog_categories()->attach($request->blog_category_id); but how to apply it correctly?

Your naming convention is complicating your task.

Rename table in categories migration:

Schema::create('categories', function (Blueprint $table) {
    $table->id();
    $table->string('title');
    $table->timestamps();
});

Also for simplicity, rename the joint (pivot) table

Schema::create('article_category', function (Blueprint $table) {
    // You don't need a table id here
    $table->foreignId('category_id')->index();
    $table->foreignId('article_id')->index();
    $table->unique(['article_id', 'category_id']);
    // You also don't need timestamps
});

Defining relationships in the models:

// Article model
public function categories()
{
    return $this->belongsToMany(\App\Models\Category::class);
}

// Category model
public function articles()
{
    return $this->belongsToMany(\App\Models\Article::class);
}

Article controller

public function store() // No need to make the function static
{
    $data = validator(request()->all(), [
        // To save many categories, send them as an array   
        'categories' => 'array',
        'categories.*' => [\Illuminate\Validation\Rule::exists('categories', 'id')], // Checks if category id is in the db
        'title' => 'required|max:128',
        'slug' => 'required|unique:articles|max:64',
        'subtitle' => 'string',
    ])->validate();

    $article = Article::create(
        \Illuminate\Support\Arr::except($data, 'categories');
    );

    // Save categories
    $article->categories()->attach($data['categories']);

    return $article;
}

According to Documentation Many To Many Relationships Attaching / Detaching

//You can pass an array of id's categories in attach method:
$article->blog_categories()->attach($categories_ids_array);

/* 
*if you want to pass more columns value you can pass an associative array of 
*column names with their values e.g attach($categories ids array, an array of 
*more columns with their values)
*/

$article->blog_categories()->attach($categories_ids_array, ['column_name' => 
$column_values]);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM