I have been asked by one of the Agile Toolkit users who have been with us since 4.1 version about how to set a maximum length on the fields and models.
On the individual basis, it's quite easy to set up the limitation, however what about creating a more sensible approach to defining length of model field? Here is how it can be done:
There are different ways to achieve things in Agile Toolkit. I am going to create a intermediate table for Model and Field. My new class for Modle will be capable of quickly checking length limitations on all the fields. The new Field class would introduce a new property "maxlength" which can be changed for any field.
Alternativevly I could have used add-on funcitonality, but it would result in a more complex code, therefore I decided to keep it simple and easy to understand.
Model fields in Agile Toolkit are described by object of "Field" class. I am going to create a class 'MyField'. You can call it differently if you wish to.
interface Interface_MaxLength {
function maxlength($t=undefined);
}
class MyField extends Field implements Interface_Maxlength{
public $maxlength=255;
function type($t=undefined){
if($t==='text' && $this->maxlength===255)$this->maxlength=null;
return parent::type($t);
}
// setting length manually
function maxlength($t=undefined){
return $this->setterGetter('maxlength',$t);
}
}
Although it was possible to create callback in each field individually, I wanted to have all the field validation to be done in the model instead. This has slight disadvantage in terms of flexibility.
class Model_MyTable extends Model_Table {
public $field_class='MyField';
function init(){
parent::init();
$this->addHook('beforeSave',array($this,'checkMaxLength'));
}
function checkMaxLength($m){
// Iterate through all fields which support maxlength
foreach($this->elements as $el)if($el instanceof Interface_Maxlength){
if($el->maxlength() && strlen($el->get()) > $el->maxlength()){
throw $this->exception('Maximum length of this field is '.
(int)$el->maxlength(),'ValidityCheck')->setField($el->short_name);
}
}
}
}
Before going further, let's test our new creation.
class Model_CategoryMaxlength extends Model_MyTable {
public $table='category';
function init(){
parent::init();
$this->addField('name')->maxLength(10);
}
}
try {
$m=$page->add('Model_CategoryMaxlength');
$m->set('name','very long name for category');
$m->save();
}catch(Exception $e){
$page->add('View_Error')->set($e->getMessage());
}
$form = $page->add('Form');
$form->setModel('CategoryMaxlength');
$form->set('name','very long name for category');
$form->addSubmit();
$form->onSubmit(function($form){
$form->update()->univ()->successMessage('Successfully Created!')->execute();
});
Defining custom field and model class can proove to be useful for other goals. In larger projects sometimes I create intermediate class between the one Agile Toolkit provides and the one I'm using. This allows me to inject functionality globally into all models of my project. This is a great technique and you are welcome to use it for your purposes.
Disqus