Yii Framework Forum: Obfuscate Form Fields Name And Id. - Yii Framework Forum

Jump to content

  • (2 Pages)
  • +
  • 1
  • 2
  • You cannot start a new topic
  • You cannot reply to this topic

Obfuscate Form Fields Name And Id.

#21 User is offline   qiang 

  • Yii Project Lead
  • Yii
  • Group: Yii Dev Team
  • Posts: 5,857
  • Joined: 04-October 08
  • Location:DC, USA

Posted 07 February 2013 - 09:50 AM

In general, I am against letting model decide the form input names. It's not about MVC worshipness.

A practical reason is that a model can be used in different form configurations. For example, the user model may be used in a search form (using GET method) which doesn't like the model class in the input names. It may also be used in a user registration form (using POST method) in which the name format isn't that critical. Or it may be used in a tabular form.
0

#22 User is offline   Onman 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 175
  • Joined: 26-December 09
  • Location:The Netherlands

Posted 08 February 2013 - 06:31 PM

View Postqiang, on 07 February 2013 - 09:50 AM, said:

In general, I am against letting model decide the form input names. It's not about MVC worshipness.


I agree. In fact, I didn't like the model-part where the field names are mapped to text labels as this mapping is a views subject.
For Yii2, isn't it possible to have an extra/intermediate class that maps field names to labels? This could improve consistency (both a user table and email-list table could have a field named 'email').
0

#23 User is offline   Mike 

  • Elite Member
  • PipPipPipPipPip
  • Yii
  • Group: Members
  • Posts: 3,013
  • Joined: 06-October 08
  • Location:Upper Palatinate

Posted 09 February 2013 - 05:51 AM

I think one root of all these problems is this vexatious CHtml class. It's too heavy and the fact that it's rather a container for helper methods than a real OO component makes it very hard to customize.

I wonder if maybe a new widget CHtmlForm would be an alternative. It would implement all the active* methods which are now in CHtml (similar to CActiveForm):

<?php $form = $this->beginWidget('CHtmlForm'); ?>
<?php echo $form->activeTextField(...) ?>


In my experience you hardly ever render an input tag without a form, thus a widget could make sense here. Input names and ids would be generetated inside this CHtmlForm class and thus are open to modification. CHtml could still be the expert on all things related to low-level HTML rendering: tags, attributes, etc. (but free of any limitations).

The form relatated static methods could als move into this new widget class:

<?php echo CHtmlForm::textField(...) ?>


Then CActiveForm could use a composition pattern to make this customizable:


<?php $form = $this->beginWidget('CActiveForm', array(
    'formClass' => 'CHtmlForm',  // default, but overridable
    ...

1

#24 User is offline   qiang 

  • Yii Project Lead
  • Yii
  • Group: Yii Dev Team
  • Posts: 5,857
  • Joined: 04-October 08
  • Location:DC, USA

Posted 11 March 2013 - 10:09 PM

I'm currently working on the form related classes in Yii 2.
I have finished the static class Html, which as suggested here, only contains low-level HTML code generation without touching any model.

Next I plan to create an ActiveForm class. Its purpose is similar to CActiveForm in 1.1, but certainly with a lot of changes. Below are some changes in my mind:

1. implement CHtml::active methods directly in ActiveForm. I do not plan to introduce another static class HtmlForm.
2. support custom input name prefixes via class name mapping. So by configuring the ActiveForm property, you can choose to use "User[email]", "myuser[email]", or "name" as the input name for the user email input.
3. better support of validation error handling. In 1.1, there are some discrepancy between js-based and server-based validation error displays, mainly because of the error class handling. I hope this can be fixed.

Anything else you would like to see in the new ActiveForm? Any suggestions?

In Yii 2, we will still have attributes() declaration in Model. I understand this in theory doesn't belong to model because it's about presentation. But I can't think of a better place to hold it, and attribute labels are certainly useful in many places. Putting them in a separate class seems too much (and if you really want to do this, you can always customize the attributes() method in the base class to implement it).
2

#25 User is offline   Mike 

  • Elite Member
  • PipPipPipPipPip
  • Yii
  • Group: Members
  • Posts: 3,013
  • Joined: 06-October 08
  • Location:Upper Palatinate

Posted 12 March 2013 - 04:30 AM

This sounds good. I also agree to your arguments for the attributes() method: I see them as meta properties of a model, same as validation errors etc.

For ActiveForm i'd love to see an improved client side implementation. We've already discussed this for the GridView here. Some features from the top of my head, which would be awesome:

1. Make the clientside form a standalone plugin. So you can create new forms on the clientside - independent of any ActiveForm on the serverside.
2. Utilize jQuery's event system for all kind of interesting moments, so that users can attach their own event handlers on the clientside
3. Provide methods to get/set form input values and validation errors/validation status

$('#my-form').yiiActiveForm({...});

// Get/set validation errors
errors = $('#my-form').yiiActiveForm('validation');
$('#my-form').yiiActiveForm('validation', { name: 'You have to enter a name', ...});


// Get/set values
values = $('#my-form').yiiActiveForm('values');
$('#my-form').yiiActiveForm('values', { name: 'Some name', ...});


// Trigger validation or submission
$('#my-form').yiiActiveForm('validate');
$('#my-form').submit();


// Bind event handler to interesting moments
//  (maybe use some custom Event objects for different types)
$('#my-form').on('beforevalidate', function(e) { ... } );

0

#26 User is offline   yJeroen 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 94
  • Joined: 06-September 11
  • Location:The Netherlands

Posted 14 March 2013 - 03:33 PM

Qiang, I don't know if this would be something for Yii2. (I'll leave that to you!) But in one of my projects, I used a custom CHtml using classmap.

I changed the resolveValue so I could more easily use related data in things like activeListBox. I also changed activeId. If I recall I did that for some ajax validation.
	/**
	* Generates input field ID for a model attribute.
	* @param CModel $model the data model
	* @param string $attribute the attribute
	* @return string the generated input field ID
	*/
	public static function activeId($model,$attribute)
	{
		$activeId = self::getIdByName(self::activeName($model,$attribute));
		$activeId = str_replace(array('.'), array('_'), $activeId);
		return $activeId;
	}
		
	/**
	* Evaluates the attribute value of the model.
	* This method can recognize the attribute name written in array format.
	* For example, if the attribute name is 'name[a][b]', the value "$model->name['a']['b']" will be returned.
	* The attribute name can be a relation set in the Model->relations() array. In that case, pass the Foreign Key attribute.
	* For example as attribute: 'relationName[ForeignKeyattribute]'
	* @param CModel $model the data model
	* @param string $attribute the attribute name or relationName[ForeignKey]
	* @return mixed the attribute value
	* @since 1.1.3
	*/
	public static function resolveValue($model,$attribute)
	{
		if(($pos=strpos($attribute,'['))!==false)
		{
			if($pos===0)  // [a]name[b][c], should ignore [a]
			{
				if(preg_match('/\](\w+)/',$attribute,$matches))
				$attribute=$matches[1];
				if(($pos=strpos($attribute,'['))===false)
				return $model->$attribute;
			}
			$name=substr($attribute,0,$pos);
			$value=$model->$name;
			if( is_array($value) && isset($value[0]) )
			{
				if( $value[0] instanceof CActiveRecord )
				{
					$relatedModels = $value;
					$value = array();
				}
			}
			elseif(isset($value) && $value instanceof CActiveRecord)
			{
				$relatedModels[] = $value;
				$value = array();
			}
			foreach(explode('][',rtrim(substr($attribute,$pos+1),']')) as $id)
			{
				if(isset($_POST[get_class($model)][$name][$id]))
					$value=$_POST[get_class($model)][$name][$id];
				else if(is_array($value) && isset($value[$id]))
					$value=$value[$id];
				else if(isset($relatedModels))
				{
					foreach($relatedModels as $relatedModel)
					{
						$value[] = $relatedModel->__get($id);
					}
				}
				else
					return null;
			}
			return $value;
		}
		else
			return $model->$attribute;
	}

0

Share this topic:


  • (2 Pages)
  • +
  • 1
  • 2
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users