philipbrown / magniloquent

DEPRECATED, USE https://github.com/dwightwatson/validating
MIT License
70 stars 8 forks source link

Make mergeRules protected? #29

Closed jfelixetcetera closed 10 years ago

jfelixetcetera commented 10 years ago

Can Magniloquent::mergeRules be made a protected method, instead of private? I'm trying to solve the unique ID problem (#22, #23, #24), and while I have a simple, decent solution, I'm not sure it's perfect for everyone. Nor am I clear if this is something you necessarily want to solve in this package. Anyway, I'd be able to solve it myself if I could just override mergeRules() in my own base model.

p.s. This is what I'm using, if it were implemented in Magniloquent. Feel free to use it, or I'll gladly open a pull request if you want. (It does change the rules in $this->mergedRules from strings to arrays to make the parsing less complicated, but that's fully supported by Validator.) But a simple change of mergeRules to protected will allow me to add this logic to my own model class.

/**
 * Merges saving validation rules in with create and update rules
 * to allow rules to differ on create and update.
 *
 * @return array
 */
protected function mergeRules()
{
    $rules = static::$rules;
    $output = array();

    if ($this->exists)
        $merged = array_merge_recursive($rules['save'], $rules['update']);
    else
        $merged = array_merge_recursive($rules['save'], $rules['create']);

    foreach ($merged as $field => $rules)
    {
        if (is_string($rules)) {
            $rules = explode('|', $rules);
        }
        $output[$field] = $this->replaceUniqueKey($rules);
    }

    $this->mergedRules = $output;
}

/**
 * Adds this model's primary key to unique rules.
 *
 * In order for unique rules to be altered, the rule must have an
 * "@key" placeholder. This should only be used in an 'update' rule.
 *
 * @example
 *     public static $rules = array(
 *         'save' => array(
 *             'email' => ['email'],
 *         ),
 *         'create' => array(
 *             'email' => ['unique:users,email'],
 *         ),
 *         'update' => array(
 *             'email' => ['unique:users,email,@key,id'],
 *         ),
 *     );
 *
 * @param array $rules
 * @return array
 */
protected function replaceUniqueKey(array $rules)
{
    array_walk($rules, function (&$rule) {
        // Only search in unique rules, as '@key' could be a literal string in another rule.
        if (strpos($rule, 'unique:') === 0) {
            $rule = str_replace('@key', $this->getKey(), $rule);
        }
    });
    return $rules;
}
w3irdrobot commented 10 years ago

Sorry for the overdue reply. I just pushed up code that should fix the unique check issue. I also made the mergeRules method protected, just for the hell of it. :)