1
votes

I have a menus table that has the following fields:

Schema::create('menus', function (Blueprint $table) {
            $table->increments('id');
            $table->string('title');
            $table->integer('page_id')->unsigned()->nullable();
            $table->integer('category_id')->unsigned()->nullable();
            $table->timestamps();
});

The condition is that the page_id and the category_id both cannot be filled simultaneously. Only one of them can be filled and the other has to be null.

In my view I let the user decide which one (s)he'd like to choose. I display a selectbox containing two items: Pages and Categories. If he chooses Pages, then another selectbox appears containing the list of pages and vice versa. Here is an example: https://imgur.com/a/EFkzF

[Much like the idea of a wordpress menu]

Here are my validation rules:

'title' => 'required|min:3',
'page_id' => 'nullable',
'category_id' => 'nullable'

And here is my $fillable array:

protected $fillable = ['title','page_id','category_id'];

In my validation rules, I cannot set page_id or category_id to required because technically only one of them is going to be required and that will be determined by the action taken by the user. It's like the Schrödinger's cat where I cannot know the state of the cat unless I open the box.

And I cannot even set them nullable, because then the form will pass the validation without page_id and category_id

How do I tackle this? Is my table design okay for situations like this? Am I following the correct strategy?

2

2 Answers

1
votes

Instead of modifying the schema, I should take advantage of the required without rules as described here: https://laravel.com/docs/5.4/validation#rule-required-without

My rules would then become:

'title' => 'required|min:3',
'page_id' => 'required_without:category_id',
'category_id' => 'required_without:page_id'

N.B.: The validation will pass if both fields are set. So you have to trick the user from the view layer. For instance, in my case, I am not showing both of the fields at the same time.

0
votes

I would do something like this

Schema::create('menus', function (Blueprint $table) {
        $table->increments('id');
        $table->string('title');
        $table->integer('item_id')->unsigned();
        $table->enum('type', ['page', 'category']);
        $table->timestamps();

});

So that in validation you could create require rule for item ID, and user can choose either page or category and that will go into enum type column 'type'.

Hope this make sense.