Potreboval som v Laraveli vytvoriť validačné pravidlo, ktoré by akceptovalo práve jeden z dvoch vstupov – nie oba naraz a aspoň jeden musel byť zadaný. Inými slovami, potreboval som na ne aplikovať logickú operáciu XOR:

ABXOR
000
011
101
110

Výsledky vyhľadávania ponúkali veľa riešení, ale žiadne z nich sa mi zvlášť nepáčilo, väčšinou kvôli ich zložitosti alebo nedostatočnej znovupoužiteľnosti. Najbližšie k minimálnej zložitosti som sa dostal použitím validačného pravidla required_without z Laravelu:

<?php

public function rules(): array
{
    return [
        input1 => [
            'required_without:input2',
        ],
        input2 => [
            'required_without:input1',
        ],
    ];
}

Toto však stále nestačilo, pretože to nie je operácia XOR, ale obyčajná OR:

ABOR
000
011
101
111

Keď by boli zadané oba vstupy, validátor by ich ochotne prijal. Po chvíli premýšľania som zistil, že v Laraveli existuje aj operátor prohibits, tak som ho použil:

<?php

public function rules(): array
{
    return [
        input1 => [
            'required_without:input2',
            'prohibits:input2',
        ],
        input2 => [
            'required_without:input1',
            'prohibits:input1',
        ],
    ];
}

Toto funguje podľa očakávania. Operácia XOR sa aplikuje na oba vstupy input1 aj input2.

Validačné správy #

Jediným nedostatkom bola vrátená validačná správa:

{
  "message": "The given data was invalid.",
  "errors": {
    "qrcode": ["validation.prohibits"],
    "code": ["validation.prohibits"]
  }
}

To znamená, že správa jednoducho nie je zadaná a vrátila sa jej „cesta”. Vyplnením cesty validation.prohibits reťazcom by sa vrátila chybová správa. Ide o základnú súčasť Laravel validátora, dokumentáciu nájdeš na odkazoch nižšie. Na zníženie opakovania kódu by výsledok mohol vyzerať takto:

<?php

public function messages(): array
{
    return [
        ...$this->customMessage('input1', 'input2'),
        ...$this->customMessage('input2', 'input1'),
    ];
}

private function customMessage(string $input, string $otherInput): array
{
    return [
        "$input.prohibits" => "The $input field is prohibited when $otherInput is present."
    ];
}

Dúfam, že to pomôže. Enjoy!

Odkazy #