Wednesday, November 23, 2011

How to read a JSON POST with Yii, and save it to the database

Let's say you are sending a json-encoded object to your create action, and want to save it in your database. here's how:

public function actionCreate() {
 
//read the post input (use this technique if you have no post variable name):
  $post = file_get_contents("php://input");

  //decode json post input as php array:
  $data = CJSON::decode($post, true);

  //contact is a Yii model:
  $contact = new Contact();

  //load json data into model:
  $contact->attributes = $data;
//this is for responding to the client:
  $response = array();

  //save model, if that fails, get its validation errors:
  if ($contact->save() === false) {
    $response['success'] = false;
    $response['errors'] = $contact->errors;
  } else {
    $response['success'] = true;
    
    //respond with the saved contact in case the model/db changed any values
    $response['contacts'] = $contact; 
  }

  //respond with json content type:
  header('Content-type:application/json');
  
//encode the response as json:
  echo CJSON::encode($response);

  //use exit() if in debug mode and don't want to return debug output
  exit();
}

Friday, October 28, 2011

Abandoning Jquery and Server-Generated HTML, moving to ExtJS + Yii backend

Our team wasted far too long trying to get our web app working with jQuery. Finally we discovered the joys of ExtJS 4, and are moving all development there.

Still using Yii as the backend for its nice models and controllers, as well as RBAC.

Saturday, August 20, 2011

Which databases does Yii support?

Yii uses PDO, which is good, as it supports parameters, which can help to prevent SQL injection attacks.

As of Yii 1.1.8, it supports the following:

  • PostgreSQL
  • MySQL
  • sqlite 3 and sqlite 2
  • Microsoft SQL Server
  • Oracle
Yii also supports dblib

Some other useful database features supported by Yii include:
  • transactions
  • schema caching for ActiveRecord
  • query caching
  • null conversion
  • database cache dependencies
  • performance profiling

Wednesday, August 10, 2011

Use session instead of stateful forms

Here's why:


  1. If you decide to use AJAX later on (in particular I mean to HIJAX your forms), you'll have to set and get the YII_PAGE_STATE variable for every action, which is a pain in the ass. 
  2. page state is broken when you try to use partial rendering. Even if the partially rendered form is a complete CActiveForm, YII_PAGE_STATE will end up blank. 
I am referring to pages that post back to themselves and that have related sub-items for which you need to maintain state. 

Saturday, August 6, 2011

How to install phpunit on Windows

the PHPUnit installer appears to be written by someone with mild autism....there's no other explanation for it.

either way, here's how i was able to install phpunit:


open the command prompt, type: (enter for each line)
  1. pear channel-update pear.php.net
  2. pear upgrade-all
  3. pear channel-discover pear.phpunit.de
  4. pear channel-discover components.ez.no
  5. pear channel-discover pear.symfony-project.com
  6. pear update-channels
  7. pear install -a -f phpunit/PHPUnit

Monday, July 18, 2011

How to output related values in json

CJSON::encode() is nice for outputting arrays of models or a dataProvider, but it doesnt output relations.

here's how to do it. This function will output an array of models, with their related values (as deep as you wanna go), in JSON format. Instead of showing every attribute, you indicate the ones you want to output using $attributeNames. The key is the CHtml::value() function, that can output related values easily.
/**
   * takes an array of models and their attributes names and outputs them as json. works with relations unlike CJSON::encode()
   * @param $models array an array of models, consider using $dataProvider->getData() here
   * @param $attributeNames string a comma delimited list of attribute names to output, for relations use relationName.attributeName
      * @return void doesn't return anything, but changes content type to json and outputs json and exits
   */

  function json_encode_with_relations(array $models, $attributeNames) {
    $attributeNames = explode(',', $attributeNames);

    $rows = array(); //the rows to output
    foreach ($models as $model) {
      $row = array(); //you will be copying in model attribute values to this array 
      foreach ($attributeNames as $name) {
        $name = trim($name); //in case of spaces around commas
        $row[$name] = CHtml::value($model, $name); //this function walks the relations 
      }
      $rows[] = $row;
    }
    header('Content-type:application/json');
    echo CJSON::encode($rows);
    exit(); //or Yii::app()->end() if you want the log to show in debug mode
  }

//usage:

$myModels = $myDataProvider->getData(); //or you can use $model->findAll();

$modelAttributeNames = 'id, subject, body, someStatisticalRelationName, someRelationName.attribute, someRelationName.someOtherRelationName.attribute';

json_encode_with_relations( $myModels, $modelAttributeNames );