0
votes

I have a user-configurable drop-down list where the user can populate it with their own list of options. I'd like to validate it with the in:foo,bar sort of validation rule.

Unfortunately, this means that some people are going to put in options like "Yes, I would". This is obviously going to break the validation if I pass an imploded list of drop-down options to the validation rule.

Is it possible to escape Laravel's rules to avoid this problem?

2
This assumes you're imploding based on commas, correct? Can yo give them a textarea and implode on newline characters? (So one item per line)fideloper
@fideloper I'd be imploding with commas as Laravel's in rule requires a comma separated list of values. Textarea doesn't help, as the user could still type a comma in one of the lines.ceejayoz
why not just remove any commas before putting in validation rule?itachi
Can you not escape the comma with a backslash? If not, maybe replace the commas in the user input with a string (like [comma]) then do the same when checking the validation?naththedeveloper
I'd prefer a neater solution, but if you post that I'll give it a +1 and accept if a better one doesn't come down the track. Thanks!ceejayoz

2 Answers

8
votes

The Validator class makes use of PHP's str_getcsv() to parse the attributes of a rule. The process goes something like:

  • Explode all rules using the | pipe delimiter (Validator::explodeRules())
  • Explode the rule name and parameters using the : colon delimiter (Validator::parseRule())
  • Send the attributes through str_getcsv() (Validator::parseParameters())

This enables you to define your list of In: options the same way you would a CSV file -- with each column in quotes! Here's an example:

$input = ['foo' => 'Hello, world!'];

// Note the formatting of the `in:` options
$rules = ['foo' => 'required|in:"StackOverflow","Laravel","Hello, world!"',];

$v = Validator::make($input, $rules);

var_dump($v->passes()); // true

Also, remember that like most things Laravel, you can extend the Validator class in whatever way suits your application. If you want something more powerful, there's no need to stick with just the "stock" out-of-the-box options. :)

1
votes

As Cryode says in his answer, Laravel decodes the allowed values as CSV. Here is a helper method you can use to produce this CSV-encoded string from an array of strings without worrying about manually escaping things.

<?php

class ValidatorHelper {

    /*
     * Get an "in" rule from a list of allowed strings
     *
     * @param array $allowed Array of allowed strings, unescaped
     * @return string In rule starting 'in:' with the allowed strings properly 
     * escaped
     */
    public static function inRule(array $allowed) {
        // Laravel separates options via CSV, so we can encode as CSV and not 
        // worry about quotes and commas in the options
        $fp = fopen('php://temp', 'r+');
        fputcsv($fp, $allowed);
        rewind($fp);
        $csv = fgets($fp);
        fclose($fp);
        return 'in:' . $csv;
    }

}

Use it like this:

$validator = new Validator(Input::all(), [
    'flavour' => [
        'required',
        ValidatorHelper::inRule([
            "mint choc chip",
            "rum and raisin",
            "orange, peach and pineapple",
        ]),
    ],
]);