Array notation in naming Form elements

Guys, here my concern.

I'm using array notation in naming my forms.

And I want to use the Phalcon\Forms\Form class to do as much as I can.

In my view I'm naming (I'll use in the future the Same) an element in this way :

<?php echo $form->render('api[name]');?>

The rendering result, reading the source code doing a GET request is:

<input type="text" class="form-control" name="api[name]" value="">

Which is what I was expecting.

Now the problem is when I'm trying to submit, since the validation is not working, and I think the problem is just with this array notation because for the other elements the validation works fine.

I have a class that extends from Phalcon\Forms\Form like:

class BricksForm extends Form
{
    public function initialize($entity = null, $options = null)
    {
        $apiName = new Text('api[name]');
        $apiName->addValidators([
            new PresenceOf([
                'message' => 'The API name is required'
                    ]),
            new StringLength([
                'min' => 3,
                'message' => 'The Name for the API has to have at least 3 characters'
                    ]),
        ]);
        $apiName->setAttributes(['class' => 'form-control']);
        $this->add($apiName);
    }
}

And when I try to submit my POST data, I'm getting errors messages for the Phalcon\Validation\Validator\PresenceOf and Phalcon\Validation\Validator\StringLength for that Phalcon\Forms\Element\Text

Am I doing something wrong? I think maybe there is a problem in the naming convention for forms. I haven't seen examples in Phalcon using array notation on elements.

Any idea?

Many thanks!

Edit:

Trying to do a more deep search in what's going on, I try to do my own Validator, just to see what's the value I'm sending to be validated. And here is the var_export:

Phalcon\Validation::__set_state(array(
   '_dependencyInjector' => NULL,
   '_eventsManager' => NULL,
   '_data' => 
  array (
    '_id' => '523fdf7b3bf3eb16.....40b',
    'name' => 'another more',
    'type' => 'related',
    'api' => 
    array (
      'name' => 'API NAME',
      'position' => '@',
      'config' => 'config',
    ),
  ),
   '_entity' => NULL,
   '_validators' => 
  array (
    0 => 
    array (
      0 => 'api[feed]',
      1 => 
      Phalcon\Validation\Validator\PresenceOf::__set_state(array(
         '_options' => 
        array (
          'message' => 'The Api Feed is mandatory',
        ),
      )),
    ),
    1 => 
    array (
      0 => 'api[feed]',
      1 => 
      Phalcon\Validation\Validator\Regex::__set_state(array(
         '_options' => 
        array (
          'pattern' => '/^[0-9]{2,4}$/',
          'message' => 'The feed has to have between 2 and 4 characters long',
        ),
      )),
    ),
    2 => 
    array (
      0 => 'api[feed]',
      1 => 
      Launchbox\Forms\Required::__set_state(array(
         '_options' => 
        array (
          'message' => 'testing message',
        ),
      )),
    ),
  ),
   '_filters' => NULL,
   '_messages' => 
  Phalcon\Validation\Message\Group::__set_state(array(
     '_position' => NULL,
     '_messages' => 
    array (
      0 => 
      Phalcon\Validation\Message::__set_state(array(
         '_type' => 'PresenceOf',
         '_message' => 'The Api Feed is mandatory',
         '_field' => 'api[feed]',
      )),
      1 => 
      Phalcon\Validation\Message::__set_state(array(
         '_type' => 'Regex',
         '_message' => 'The feed has to have between 2 and 4 characters long',
         '_field' => 'api[feed]',
      )),
    ),
  )),
   '_values' => NULL,
))

You can see that $data['feed'] has what I need, but the $_values is NULL.

I tried to see in the documentation the method but seems that the documentation has a wrong link. You can see the link http://api.phalconphp.com/en/1.2.3/Phalcon/Validation/ValidatorInterface#validate-details and the Phalcon\Validator is a 404....



4.7k

Did you solve this maybe? How to do validation on Array notation naming?



4.0k

sadly I never found a solution for that problem.

I had to change the way my Form was working

I also wonder this



34.0k
edited Jan '15

I ended up with this validator (needs improvement, but it works for names like element[key] )

<?php
namespace App\Core\Validation\Validator;

use Phalcon\Validation\Validator,
    Phalcon\Validation\ValidatorInterface,
    Phalcon\Validation\Message;

class PresenceOf extends Validator implements ValidatorInterface
{

    /**
     * Executes the validation
     *
     * @param  Phalcon\Validation $validator
     * @param  string             $attribute
     * @return boolean
     */
    public function validate($validator, $attribute)
    {
        if (is_null($attribute)) {
            return false;
        }

        preg_match_all('#\b[a-z]*\b#i', $attribute, $match);

        $value   = $validator->getValue($match[0][0]);
        $message = $this->getOption('message');

        if (is_array($value)) {
            foreach ($match[0] as $key => $val) {
                if ($key > 0 && $val != '') {
                    if (array_key_exists($val, $value) && strlen($value[$val]) > 0) {
                        return true;
                    } else {
                        $validator->appendMessage(new Message($message, $attribute));
                        return false;
                    }
                }
            }
        } else {
            return parent::validate($validator, $attribute);
        }

        return false;
    }
}

In my form I append fields dynamically based on the available languages:

use App\Core\Validation\Validator\PresenceOf;

class MyForm
{
    public function initialize($entity=null, $options=null)
    {
        $av_languages = $this->getDI()->get('config')->i18n->available_languages->toArray();

        foreach ($av_languages as $code => $language) {
            $field = new Text('name['.$code.']');

            $field->addValidator(new PresenceOf(array(
                'message' => sprintf('%s is required', $language)
            )))->setFilters('trim');

            $this->add($field);
        }
    }
}

An other way would be to flatten the values before to inject them in the Validation object, making them available for any existing Validator. At least that's the purpose, it needs to be check for more cases :

<?php
namespace Lib;

use Phalcon\Validation as LegacyValidation;

class Validation extends LegacyValidation {

  public function validate($data = null, $entity = null) {

    $recursive_flattener = function($data, $root = true) use (&$recursive_flattener) {
      $intermediate_data = array();
      foreach($data as $field => $subdata) {
        $added_key = $root ? $field : "[{$field}]";
        if(is_array($subdata)) {
          foreach($recursive_flattener($subdata, false) as $subfield => $finaldata) {
            $flatten_data["{$added_key}{$subfield}"] = $finaldata;
          }
        } else {
          $flatten_data[$added_key] = $subdata;
        }
      }
      return $flatten_data;
    };

    return parent::validate($recursive_flattener($data), $entity);

  }

}
<?php

namespace Lib\Forms;
use Phalcon\Forms\Form as LegacyForm;
use Lib\Validation as CustomValidation;

class Form extends LegacyForm {

  public function getValidation() {
    return new CustomValidation();
  }

}
<?php
use Lib\Forms\Form as CustomForm
class MyForm extends CustomForm {

    .... // classical use

}


4.5k
edited Mar '16

Using array notation in form is really issue.

  • $request->getPost('el[index1]') dont work
  • Validators dont work.