Love Fuel?    Donate

FuelPHP Forums

Ask your question about FuelPHP in the appropriate forum, or help others by answering their questions.
Working with Fieldset class and ORM
  • Hello, First : sorry for my long message. I'm trying to learn Fuel, but I have some problems with Fieldset class and Orm.
    I've create a Model which extends ORM, in order to get an automatic generated form, according to my database. My Model :
    <code>
    class Model_Product extends \Orm\Model
    { protected static $_table_name = 'products';
    protected static $_properties = array( 'id' => array('data_type' => 'int'), 'name' => array(
    'data_type' => 'varchar',
    'label' => 'Name',
    'validation' => array('required', 'trim', 'max_length'=>array(30),
    'min_length'=>array(3)),
    ), 'description' => array(
    'data_type' => 'varchar',
    'label' => 'Description',
    'validation' => array('max_length'=>array(290)),
    'form' => array('type' => 'textarea')
    ), 'price' => array(
    'data_type' => 'integer',
    'label' => 'Price',
    'validation' => array('required', 'trim', 'valid_string'=>array('numeric','dots') )
    ), 'pic' => array(
    'data_type' => 'varchar',
    'label' => 'Path to the pic',
    'validation' => array('required', 'trim')
    ), 'registered' => array(
    'data_type' => 'date',
    'label' => 'Registration date',
    'validation' => array('required', 'trim') //'valid_string' => array('numeric','dashes')
    ), ); } //end of class Model_Product
    </code> Than i create the controller which will validate the form. My function from the controller : <code> function action_add()
    {
    $fieldset = Fieldset::forge('add_product')->add_model('Model_Product')->repopulate(); $form = $fieldset->form(); $form->add('submit', '', array('type' => 'button', 'value' => 'Add item', 'class' => 'button-link' )); $validation = $fieldset->Validation(); if($validation->run() === true)
    {
    $fields = $fieldset->validated(); //create a new Product, with validated fields
    $product = new Model_Product; $product->name = $fields;
    $product->description = $fields;
    $product->price = $fields;
    $product->pic = $fields;
    $product->registered = $fields; try
    {
    //if the product is successfully inserted in the database
    if($product->save())
    {
    Session::set_flash('success', 'Product successfully added !');
    \Response::redirect('products/product_details/'.$product->id);
    } }
    catch(Exception $e)
    {
    Session::set_flash('error', 'Unable to save the product into the database !'.$e->getMessage());
    } }
    //If the validation doesn't pass
    else
    {
    Session::set_flash('error', $fieldset->show_errors());
    } $this->template->set('content', $form->build(), false); } // end of method add() </code> My first question :
    How and where can i add a 'fieldset' tag with a specific class, in order to 'beautify' my auto-generated form ?
    Let's say
    <code>
    fieldset class="add_product"
    </code> Second question :
    What do I have to do in order to correctly validate de 'price' field, because in MySQL is set as decimal(5,2), but when I'm trying to validate with my actual validation rule, it doesn't pass (it works only with integer values Ex.: 42, but not with decimal Ex.: 42.35). I have tried to change the type from 'integer' to 'double', but it doesn't work . Please help me with this 'small' problems ! If you can point to some specific documentation regarding my problems, which I possible didn't read, please do it. Gabriel
  • The fieldset form is generated following the template you define. If none is defined, it will use the template defined in the form.php config file. If you app doesn't have one, it's loaded from core/config. Note that these templates are quite simple, you should not expect magic generation of any elaborate design. If you want to do that, you'll have to build the form manually in the view. This is an example from one of my apps: http://scrp.at/bwb As to validation, you can define any rule that is callable. This can be:
    - one of the built-in rules you find in the documenation
    - an array ($object, 'method')
    - a static method reference "class::method"
    - a closure
    - any built-in PHP function that accepts a single argument and returns true/false In your case, probably "required|trim|is_numeric" would probably already do the trick.
  • Thank you very much for your time and also for the answers. It really helps, but I want to clarify something, for myself, and please let me know if I am wrong.
    For my first question everything is clear now. I have to create the form in the View, in order to beautify it. From the view, through the form, I am calling the Controller, which contains my validation method. So, for this aspect, using ORM to auto-generate forms is not the best choice. For my second question regarding the validation: In MySQL, I create a table, and every field has his own characteristics (Exp. : null, varchar(183), not null, blob, …).
    Is there a possibility to grab these characteristics through the ORM, and to automatically create the minimum validation rule according to these characteristics? Following your notes regarding the validation rules, I have created a new method in my Controller, which looks like that: //add new product
    function action_validate()
    {
    $this->template->title = 'Add new product'; $val = Validation::forge('add_product'); //rules for the fields
    $val->add_field('name', 'Product name', 'required|trim|min_length[3]|max_length[30]');
    $val->add_field('price', 'Product price', 'required|trim|is_numeric');
    $val->add_field('pic', 'Path to the pic', 'required|trim');
    $val->add_field('registered','Registration date','required|trim|valid_string[numeric,dashes]'); //create custom error messages
    $val->set_message('name', ':min_length must be at least 3 characters');
    $val->set_message('name', ':max_length must have maximum 30 characters');
    $val->set_message('is_numeric', ':label must be numeric');
    $val->set_message('valid_string', "Please use this format '2012-06-18' for a valid date on field :label"); //if the validation passed
    if($val->run() === true)
    {
    //create an array with validated fields.
    $fields = $val->validated(); //create a new Product, with validated fields
    $product = new Model_Add; $product->name = $fields;
    $product->price = $fields;
    $product->pic = $fields;
    $product->registered = $fields; //if the user doesn't entry a description, we alocate a default text
    isset($fields) ? $product->description = $fields : $product->description = 'No description available'; try
    {
    //try to insert the product in database
    if($product->save())
    {
    Session::set_flash('success', 'Product successfully added !');
    \Response::redirect('products/product_details/'.$product->id);
    } }
    //if we cannot save the product in database
    catch(Exception $e)
    {
    Session::set_flash('error', 'Unable to save the product into the database !');
    } }
    //if the validation failed
    else
    {
    Session::set_flash('error', $val->show_errors());
    } $this->template->content = View::forge('products/add_product'); } // end of method validate()
    It works very well, it validates ok, but I have a strange feeling that is not quite the best piece of code for what should do. Am I wrong or not? It is difficult, when you don’t have who to ask for a professional opinion, so please be so kind, and let me know if it is ok, or what should I improve / radically change. Many thanks in advance.
  • You are right, the best place to define your validation rules is in the model. You can define the field rules as part of the $_properties in the ORM model. From the model that drives the form I showed you: http://scrp.at/bwi. The valid_* rules in there refer to methods in the model that do custom validation. You access those rules like so:
    // create the form fieldset
    $form = Fieldset::forge('form');
    // load the properties from the model
    $form->add_model('Model_Registration');
    // make sure the custom rules can be found
    $form->validation()->add_callable('Model_Registration');
    // run the validation
    $form->validation()->run();
    
    This allows you to define basic validation rules, and usually that is enough. Alternatively, if you need more complex stuff, you can also forge a validation object in the model, so you can add whatever you want to it. Like so: http://scrp.at/bwj. You can also use this when you don't need form objects.
  • Thank you very much again for your time and precious advices. +1

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

In this Discussion