Currently Browsing: Yii

Yii2 fix “Malformed UTF-8 characters” error with master/slave db

You need to specify charset in slave config, e.g.,

'slaveConfig' => [
  'charset' => 'utf8',

PHP 7 from Docker container complete with Yii 2.0

Pretty cool, a PHP 7.0 (RC4) with Apache environment on Mac from scratch in a few minutes via Docker container:

Includes installation for minimal requirements to support Yii 2.0

Uses Vagrant + VirtualBox on Mac (or similar) or instead you can use any existing Docker host.

Multiple databases in Yii: MySql + SQLite

If you need two (or more) completely different db connections in the same app (e.g, MySql + SQLite), using this method works better than trying to dynamically change the static variable CActiveRecord::db. (If you are using multiple MySql dbs you could get away with a more simple solution like that, which could even take advantage of cross-db queries, which this method won’t.)

In this example, we want to read/write press release data to SQLite for the Press model:

  • main config file:
    	'dbpress' => array(
    		'connectionString'	=> 'sqlite:' . '/path/to/press.db',
    		'charset' => 'utf8',
    		'class' => 'CDbConnection'
  • Press model:
    class Press extends CActiveRecord
    // second db support:
        private static $dbpress = null;
        protected static function getPressDbConnection()
            if (self::$dbpress !== null)
                return self::$dbpress;
            else {
                self::$dbpress = Yii::app()->dbpress;
                    return self::$dbpress;
        public function getDbConnection()
            return self::getPressDbConnection();
  • that’s it!

    Yii CArrayDataProvider add case-sensitive option

    In Yii if you use CArrayDataProvider for a data set, it will use PHP’s array_multisort for sorting, which is normally case sensitive so if you have any items that aren’t capitalized, it will mess up the order and is inconsistent with how MySql sorts.

    And now that I realize this extra sorting step is happening (and it certainly makes sense to do it that way, Yii doesn’t know where my data originally came from) — I may re-think where I’m using this to see if it can be done via a database (CActiveDataProvider) search since I’m usually fetching the data from the db anyway and it would be more efficient to have MySql sort it at the time it’s requested.

    In any case – if for whatever reason you are not using a db connection for the data or really do have to do some pre-processing before handing off to CArrayDataProvider, here is how you can add a case-sensitive switch:

    Click here to view code

    Override CArrayDataProvider to provide a custom sortData method and add an additional property to toggle the custom bit:

    class myCArrayDataProvider extends CArrayDataProvider {
    	public $casei = false;
    	protected function sortData($directions)
    		foreach($directions as $name=>$descending)
    			foreach($this->rawData as $index=>$data)
    				$column[$index]=is_object($data) ? $data->$name : $data[$name];
    			$direction=$descending ? SORT_DESC : SORT_ASC;
    		if ($this->casei) { 
    			for ($i = 0; $i < count($args); $i++) {
    				$args[$i] = (is_array($args[$i])) ? 
                                              array_map('strtolower', $args[$i]) : $args[$i];
    		call_user_func_array('array_multisort', $args);

    Then when creating your dataProvider:

    $dataProvider = new myCArrayDataProvider($proj_result, array(
      [rest of your params...]
    $dataProvider->casei = true;

    If you always wanted it case insensitive you could leave out the "casei" param.

    Yii: use ajax function via htmlOptions attribute

    If you want to trigger an ajax call on a Yii form element onchange, you can pass an array of ajax attributes as one of the “htmlOptions” like so:

    <?php echo $form->textField($model,'my_input_field',array(
    	'ajax' => array(
    		'type'=>'POST', //request type
    		'url'=>$this->createUrl('site/ajaxAction'), // url to call controller action
    		'success'=>' function(data) { $(\'#my_output_field\').val(data) }',// function to call onsuccess 
                 // "data" is returned data and function can be regular js or jQuery
                 // here we are are updating the value of another field that has id "my_output_field"
    )); ?>

    and the (site) controller action would look something like:

    public function actionAjaxAction() {
      [check/filter inputs...]
      [data functions...]
      echo $my_val_string;

    « Previous Entries