Yii Framework Forum: Composite Unique (Key) Validator - Yii Framework Forum

Jump to content

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

Composite Unique (Key) Validator Rate Topic: -----

#1 User is offline   c@cba 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 43
  • Joined: 02-December 11

Posted 29 December 2013 - 07:29 AM

ECompositeUniqueValidator validates that the combined values of the given attributes (composite key) is unique in the corresponding database table.

It is a modification of the build in CUniqueValidator. All properties and methods of the CUniqueValidator should also work with this validator, with the exception of the property attributeName.

Requirements
Tested with Yii 1.1.9, should work with Yii 1.1 or above.

Usage

Files
Extract the zip file.
Put everything under ECompositeUniqueValidator/components into your protected/components folder.
Put everything under ECompositeUniqueValidator/extensions into your protected/extensions folder.
Make sure that the extension is imported in your config file protected/config/main.php:

'import'=>array(
	...
	'ext.ECompositeUniqueValidator',
	// 'ext.*', // <---- this works too
),



Example 1 (basic)
In your model file:

public function rules()
{
	return array(
		array('book_id, tag', 'ECompositeUniqueValidator'),
		...
	);
}

This rule ensures that each (book_id, tag) combination is unique in the corresponding database table.


Example 2
In your model file:

public function rules()
{
	return array(
		array('book_id, tag', 'ECompositeUniqueValidator', 
			'attributesToAddError'=>'tag',
			'message'=>'The tag {value_tag} already exists for this book.'),
		...
	);
}

The property attributesToAddError defines to which attribute(s) the error message should be added to, if a validation error occurrs. It should be a comma separated list of attributes. If not specified, the error will be added to the first attribute in the list of attributes.
The placeholder {value_tag} will be replaced with the current value of the attribute tag.


Documentation

Placeholders
When using the message property to define a custom error message, the message
may contain additional placeholders that will be replaced with the actual content.
ECompositeUniqueValidator allows for the following placeholders to be specified:

- {attributes}: replaced with a comma separated list of the labels of the given attributes.
- {values}: replaced with a comma separated list of the current values of the given attributes.
- {value_"attr"}: replaced with the value of the given attribute named "attr".
- {attr_"attr"}: replaced with the label of the given attribute named "attr".
For example, use {attr_tag} and {value_tag} to get the label and the value of the attribute tag (see Example 2 above).

Properties
ECompositeUniqueValidator introduces two additional public properties:
- attributesToAddError: comma separated list of attributes, to which the error message should be added (see Example 2 above).
- attributeNames: replaces the property attributesName of the CUniqueValidator. Thus, it is a comma separated list of
the ActiveRecord class attribute names that should be used to look for the attribute values being validated.
Defaults to null, meaning using the names of the attributes being validated.

The Component
The abstract class CValidator
does not facilitate a combined validation of multiple attributes. Rather, each attribute is validated separately.
We circumvent this by extending the CValidator and overriding its validate() function, which is where the attributes are separately sent to the validator (see class file Validator.php for details).
The Validator class introduces a new property:

- enableCombinedValidation: If set to true, all attributes are sent to the validator at once. Defaults to null, meaning each attribute is validated separately (default behaviour).

The ECompositeUniqueValidator is derived from Validator and has enableCombinedValidation set to true, therefore all listed attributes are validated together.

Resources
- extension page
- composite-unique-key-validatable : An extension, that also validates composite unique keys of AR-models, implemented as a behaviour.
- unique-attributes-validator : Another extension that validates unique constraints with more then one attribute.

That's it. If you find bugs or have suggestions for improvements, please let me know.
0

#2 User is offline   Andrey Pesoshin 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 2
  • Joined: 09-January 14

Posted 25 January 2014 - 06:15 AM

Hi! Thanks for your great work.

Just a small thing - why Validator.php needs to be located in components/ folder but not in extensions/ together with ECompositeUniqueValidator?

As far as I understood, all extra logic (called extensions here) is better to be used "as-is" without modifications and placed into some dedicated folder inside extensions folder. In other hand, components are to be modificated as they belong to certain application level.

Looking through the code and wikis on github also gets no explantion of it.
0

#3 User is offline   c@cba 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 43
  • Joined: 02-December 11

Posted 25 January 2014 - 07:06 AM

View PostAndrey Pesoshin, on 25 January 2014 - 06:15 AM, said:

Hi! Thanks for your great work.

Just a small thing - why Validator.php needs to be located in components/ folder but not in extensions/ together with ECompositeUniqueValidator?

As far as I understood, all extra logic (called extensions here) is better to be used "as-is" without modifications and placed into some dedicated folder inside extensions folder. In other hand, components are to be modificated as they belong to certain application level.

Looking through the code and wikis on github also gets no explantion of it.


Hi!

I don't know if there is a standard way or a "best practice" for structuring the files in extensions. I developed a few extensions so far, and every time I change the way I locate files due to new considerations.

In my yii applications I put my custom component files always directly unter components/ since I often use them throughout the application, not just in one extension. This way I also don't need to import everything separately in the config file; 'ext.*' and 'components.*' cover them all.

For example, what should I do in the following scenario: I have an extension with its custom "SomeActiveRecord.php" class, that needs me to derive my model files from it. On the other hand I have my own "OtherActiveRecord.php" class with a bunch of extra stuff.
For the time being I combine the two in one "ActiveRecord.php" class located under "components/"

On the other hand, I agree that when sharing extensions with the public, it makes sence to have everything "bundled" in one place.

I'd be really interested in the opinions of the more experienced staff members on this topic.

Best regards...
c@cba
0

#4 User is offline   c@cba 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 43
  • Joined: 02-December 11

Posted 25 January 2014 - 07:17 AM

For example:
Does it makes sense to use the following directory structure; and to put the files of the extensions we download into the respective directories?
extensions/
	assets/
		js/
		css/
		img/
	components/
	messages/
		de/
		en/
		...
	models/
	views/

0

#5 User is offline   Andrey Pesoshin 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 2
  • Joined: 09-January 14

Posted 01 February 2014 - 01:56 PM

As far as I understood, Yii docs at http://www.yiiframew...xtension.create provide no considerations on internal directory structure of the extension. It also claims that the extension should be self-contained and organized under one directory.

So my opinion is that you have freedom in organizing your extension files in any fashion as long as the extension stays self-contained with files located under the same directory.

At the same time I can't see any reason for locating Validator.php under components/ directory instead of extensions/, because a Validator class is not being used anywhere else but in ECompositeUniqueValidator class.
Maybe it is some?

As for the scenario you described, to keep an application code DRY-ed, there should be no class components/ActiveRecord.php that simply duplicates methods of two classes - extension/SomeActiveRecord.php and your components/OtherActiveRecord.php. As SomeActiveRecord should be untouched and used "as-is" (cause it belongs to extension), you could either derive your OtherActiveRecord from SomeActiveRecord, or use behaviors mechanism to add some extra logic to your base AR class without changing inheritance hierarchy.
0

#6 User is offline   c@cba 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 43
  • Joined: 02-December 11

Posted 02 February 2014 - 08:10 AM

View PostAndrey Pesoshin, on 01 February 2014 - 01:56 PM, said:

At the same time I can't see any reason for locating Validator.php under components/ directory instead of extensions/, because a Validator class is not being used anywhere else but in ECompositeUniqueValidator class.
Maybe it is some?

As for the scenario you described, to keep an application code DRY-ed, there should be no class components/ActiveRecord.php that simply duplicates methods of two classes - extension/SomeActiveRecord.php and your components/OtherActiveRecord.php. As SomeActiveRecord should be untouched and used "as-is" (cause it belongs to extension), you could either derive your OtherActiveRecord from SomeActiveRecord, or use behaviors mechanism to add some extra logic to your base AR class without changing inheritance hierarchy.


In instances where the component provides a new "general" feature, that will probably be used by more than just one extension, it might make sense to place it under protected/components/.
For example, I plan to develop a new validator extension that ensures at least one of several attributes to be non-empty. This extension will also be derived from Validator.php.

But I get the point and you're right about the self-containedness; I think in the next version of the extension I'll put everything into one folder.
In my own application tough I will keep Validator.php under components/, along with several other derived classes (GridView, DataColumn, ButtonColumn etc.) because of the reasons above.

In case of the ActiveRecord, I don't have duplicate code since I re-located the code (combined in one file, deleted the orher two). I'm not comfortable with it (i.e. moving around extension-code), but I couldn't find another way in my specific case. I'll rethink if I could use the behaviors mechanism, since I didn't try very hard to make this one work back then...

In any case, thanks for the feedback!
Best regards...
0

Share this topic:


Page 1 of 1
  • 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