Tuesday, July 9, 2013

Yii: Highlighting code with Yii

If you are posting code, be it company's internal wiki or a public developer's blog, it is always better to have the syntax highlighted, so ones who read the code will feel comfortable. Yii has Pear Text_Highlighter code-highlighting class bundled. It is used to highlight Yii definitive guide examples and we can use it to do the same for our application. In this recipe, we will create a simple application that will allow adding, editing, and viewing code snippets.

Getting ready

  • Create a new application by using yiic webapp as described in the official guide at the following URL:
  • http://www.yiiframework.com/doc/guide/en/quickstart.first-app
  • Set up a database connection and create a table named snippet as follows:
  • CREATE TABLE `snippet` (
       `id` int(11) unsigned NOT NULL auto_increment,
       `title` varchar(255) NOT NULL,
       `code` text NOT NULL,
       `html` text NOT NULL,
       `language` varchar(20) NOT NULL,
       PRIMARY KEY (`id`)
    );
    
  • Generate a Snippet model by using Gii

How to do it...

  1. First, we will tweak the protected/models/Snippet.php model code. Change rules method to the following:
  2.     public function rules() {
            return array(
                array('title, code, language', 'required'),
                array('title', 'length', 'max' => 255),
                array('language', 'length', 'max' => 20),
            );
        }
    
  3. Add methods to the same Snippet model:
  4.     protected function afterValidate() {
            $highlighter = new CTextHighlighter();
            $highlighter->language = $this->language;
            $this->html = $highlighter->highlight($this->code);
            return parent::afterValidate();
        }
    
        public function getSupportedLanguages() {
            return array(
                'php' => 'PHP',
                'css' => 'CSS',
                'html' => 'HTML',
                'javascript' => 'JavaScript',
            );
        }
    
  5. The model is ready. Now we will create a controller. Therefore, create protected/controllers/SnippetController.php as follows:
  6. order = 'id DESC';
            $models = Snippet::model()->findAll();
            $this->render('index', array(
                'models' => $models,
            ));
        }
    
        public function actionView($id) {
            $model = Snippet::model()->findByPk($id);
            if (!$model)
                throw new CException(404);
            $this->render('view', array(
                'model' => $model,
            ));
        }
    
        public function actionAdd() {
            $model = new Snippet();
            $data = Yii::app()->request->getPost('Snippet');
            if ($data) {
                $model->setAttributes($data);
                if ($model->save())
                    $this->redirect(array('view', 'id' => $model->id));
            }
            $this->render('add', array(
                'model' => $model,
            ));
        }
    
        public function actionEdit($id) {
            $model = Snippet::model()->findByPk($id);
            if (!$model)
                throw new CHttpException(404);
            $data = Yii::app()->request->getPost('Snippet');
            if ($data) {
                $model->setAttributes($data);
                if ($model->save())
                    $this->redirect(array('view', 'id' => $model->id));
            }
            $this->render('edit', array(
                'model' => $model,
            ));
        }
    
    }
    
  7. Now views; create protected/views/snippet/index.php as follows:
  8. Snippets

    1. title), array('view', 'id' => $model->id) ) ?>
  9. Create protected/views/snippet/view.php as follows:
  10. title) ?>

    $model->id)) ?>
    html ?>
  11. Create protected/views/snippet/add.php as follows:
  12. → Add snippet

    renderPartial('_form', array('model' => $model))?>
  13. Create protected/views/snippet/edit.php as follows:
  14. → Edit snippet

    renderPartial('_form', array('model' => $model))?>
  15. Create protected/views/snippet/_form.php as follows:
  16. 
    
    • getSupportedLanguages()) ?>
  17. That is it. Now run the snippet controller and try creating code snippets, as shown in the following screenshot:
  18. When it is viewed, it will look similar to the following:

How it works...

The snippet model's function is used to store the code and snippet title. Additionally, we have added the html and language fields. The first one (html) is used to store HTML representing the highlighted code and the language field is used for the snippet language (PHP, HTML, CSS, JavaScript, and so on). We need to store these, as we need them when we edit the the snippet. As we remove the safe rule from the Snippet model, we make title, code, and language as the required fields. There is no rule for html which means that it cannot be set through the form directly. The afterValidate method—as its name states—is executed after the validation gives us no errors. In this method, we transform the code which is stored in the code field to HTML representing the highlighted code in the html field by using the Yii's CTextHighlighter class and passing the language value to it. getSupportedLanguages returns languages we want to support in the value-label array. We use this method in the snippet form.

There's more...

In order to learn more about code highlighting, you can use the following resources:

Yii code highlighter
  • http://www.yiiframework.com/doc/api/CTextHighlighter
  • http://pear.php.net/package/Text_Highlighter/

More code highlighters
If Text_Highlighter bundled with Yii does not fit your needs, then there are many code highlighters available on the Internet. A few good examples are:
  • http://qbnz.com/highlighter/
  • http://softwaremaniacs.org/soft/highlight/en/

20 comments: