Search code examples
phpyii

Yii: model attribute's comments/hints


I need to have comments/hints for some fields in my Form. My idea is to describe it in model, just like attributeLabels. How can I do it?

And then it would be ideal, if the Gii Model (and Crud) generator would take it directly from mysql column's comment


Solution

  • So I see two questions here:

    1. Describe hints in the model and display on the form.
    2. Get hints from mysql comment

    Displaying Hints from Model

    Here's a slightly modified version of the default login.php file generated by Yiic

    <div class="form">
    <?php $form=$this->beginWidget('CActiveForm', array(
        'id'=>'login-form',
        'enableClientValidation'=>true,
        'clientOptions'=>array(
            'validateOnSubmit'=>true,
        ),
    )); ?>
    
        <p class="note">Fields with <span class="required">*</span> are required.</p>
    
        <div class="row">
            <?php echo $form->labelEx($model,'username'); ?>
            <?php echo $form->textField($model,'username'); ?>
            <?php echo $form->error($model,'username'); ?>
        </div>
    
        <div class="row">
            <?php echo $form->labelEx($model,'password'); ?>
            <?php echo $form->passwordField($model,'password'); ?>
            <?php echo $form->error($model,'password'); ?>
            <p class="hint">
                Hint: You may login with <kbd>demo</kbd>/<kbd>demo</kbd> or <kbd>admin</kbd>/<kbd>admin</kbd>.
            </p>
        </div>
    
        <div class="row rememberMe">
            <?php echo $form->checkBox($model,'rememberMe'); ?>
            <?php echo $form->label($model,'rememberMe'); ?>
            <?php echo $form->error($model,'rememberMe'); ?>
        </div>
    
        <div class="row buttons">
            <?php echo CHtml::submitButton('Login'); ?>
        </div>
    
    <?php $this->endWidget(); ?>
    </div><!-- form -->
    

    Let's move that password hint into the model by adding a attributeHints() method and a getHint() method to the LoginForm.php model.

        /**
         * Declares attribute hints.
         */
        public function attributeHints()
        {
            return array(
                    'password'=>'Hint: You may login with <kbd>demo</kbd>/<kbd>demo</kbd> or <kbd>admin</kbd>/<kbd>admin</kbd>.',
            );
        }
    
        /**
         * Return a hint
         */
        public function getHint( $attribute )
        {
            $hints = $this->attributeHints();
    
            return $hints[$attribute];
        }
    

    As you can see, we;ve moved the hint text from the view into the model and added a way to access it.

    Now, back in login.php, let's add the hint tag based on data from the model.

    <div class="row">
        <?php echo $form->labelEx($model,'password'); ?>
        <?php echo $form->passwordField($model,'password'); ?>
        <?php echo $form->error($model,'password'); ?>
        <?php echo CHtml::tag('p', array('class'=>'hint'), $model->getHint('password')); ?>
    </div>
    

    So now we've changed the hardcoded hint into a generated element populated with data from the model.

    Now, moving on to the second question.

    Getting hints from mySQL comments

    Unforunately, I am not fammiliar enough with Gii to know how to automatically generate the hints from mySQL comments. However, getting the mySQL comment data into the model is fairly easy.

    To do this we can use the following mySQL query

    SHOW FULL COLUMNS FROM `tbl_user`
    

    So let's add the comment to the password field

    ALTER TABLE  `tbl_user` 
    CHANGE  `password`  `password` VARCHAR( 256 ) 
    CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL 
    COMMENT  'Hint: You may login with <kbd>demo</kbd>/<kbd>demo</kbd> or <kbd>admin</kbd>/<kbd>admin</kbd>.';
    

    And let's add the code to fetch it into our attributeHints() method.

        /**
         * Declares attribute hints.
         */
        public function attributeHints()
        {
            $columns= Yii::app()->db->createCommand('SHOW FULL COLUMNS FROM `tbl_user`')->queryAll();
    
            $comments=array();
            foreach($columns as $column){
                if( isset( $column['Comment'] ) )
                {
                    $comments[ $column['Field'] ] = $column['Comment'];
                }
    
            }
    
            //Add any hardcoded hints here
            $hints = array(
                    'username'=>'Enter username above',
            );
    
            //Return merged array
            return array_merge( $comments, $hints );
        }
    

    We now have two ways to set comments, through mySQL comments or through hard coded statements.

    Let's update our login.php file quick to include hints of both types.

    <div class="row">
        <?php echo $form->labelEx($model,'username'); ?>
        <?php echo $form->textField($model,'username'); ?>
        <?php echo $form->error($model,'username'); ?>
        <?php echo CHtml::tag('p', array('class'=>'hint'), $model->getHint('username')); ?>
    </div>
    
    <div class="row">
        <?php echo $form->labelEx($model,'password'); ?>
        <?php echo $form->passwordField($model,'password'); ?>
        <?php echo $form->error($model,'password'); ?>
        <?php echo CHtml::tag('p', array('class'=>'hint'), $model->getHint('password')); ?>
    </div>
    

    And that's it!

    Login page

    Now our login page will look like this, with a username hint from the model and a password hint from the mySQL comment.