Showing posts with label php. Show all posts
Showing posts with label php. Show all posts

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 );

Thursday, April 28, 2011

Yii » Missing Features

This will be an ongoing list. Check back in the future.

  1. Yii needs a grid that you can edit inline - maybe jqgrid for version 2?
  2. The listData->groupField works nicely on dropDownLists, but it would be nice it it worked on checkBoxLists and radioButtonLists too (displaying the category name and indenting associated controls)
  3. No concurrency control. It would be nice in Gii if it could generate models that saved the original record values, as well as using them to check for concurrency when saving. 
  4. Easier to use some of the new HTML 5 controls, like "search"
  5. Built-in basic search on lists (much like on grids)
  6. Easier tabular input
  7. When you do ajax on a grid (sort or page), it reloads the whole page, finds the grid content, and replaces itself. This is a little inefficient ;) . It would be better if Gii could split the grids out to separate partial views. 
  8. Yii seems to get confused sometimes when you have nested JQuery UI controls
  9. It would be better if the built-in Blueprint theme was mobile-friendly out of the box, and by that I mean side by side columns that collapse on top of each other on small width screens, perhaps switch to the 1140 grid system
  10. use superfish on multi-level menus out' the box
  11. ZeroClipboard, jQuery WYSIWYG editor, and fullcalendar support out' the box.
  12. phpMailer, a flash/html5/silverlight multi-uploader, vcard, pdf, ics support out' the box

Saturday, March 5, 2011

How to make a mobile theme in Yii

Making a mobile theme in Yii is pretty easy. Getting it running smoothly is more work. Here's how:

Making the Theme


1. under /themes/ create a folder "mobile"

2. copy main.php from /protected/views/layouts/ to the /themes/mobile/views/layouts/ folder. You don't need to copy anything else. Views, etc will be inherited.

3. The blueprint CSS framework doesn't seem to be too mobile friendly. By default, there will be a lot of horizontal scrolling. So, in /themes/mobile/views/layouts/main.php, remove these lines:

<!-- blueprint CSS framework -->
<link rel="stylesheet" type="text/css" href="<?php echo Yii::app()->request->baseUrl; ?>/css/screen.css" media="screen, projection" />
<link rel="stylesheet" type="text/css" href="<?php echo Yii::app()->request->baseUrl; ?>/css/print.css" media="print" />
<!--[if lt IE 8]>
<link rel="stylesheet" type="text/css" href="<?php echo Yii::app()->request->baseUrl; ?>/css/ie.css" media="screen, projection" />
<![endif]-->

You can test it out by setting 'theme'=>'mobile' in /protected/config/main.php

Now, you want to detect the browser type and set the right theme (which i'll cover next), BUT you also want to give users a choice. For example, you should be able to test the mobile site on your desktop web browser, without changing the user-agent string.

* one thing you may not know is that Yii looks for the classic theme on start, which is empty. But you can put views or layouts there and they will be used without configuration change.

You can add some styling to the mobile theme to make it look better. Here are some items to consider:



<style>
    input[type=text], input[type=password], textarea {max-width:260px;}
    h1,h2,h3,h4,h5,h6 {font-weight:normal;}
    html, body, #content {margin:0; padding:0;}
    #content h1, #logo, #footer, .portlet-title {display:none;}
    #sidebar {padding:0; margin:0; margin-top:5px;}
    * {float:none; }
</style>


Wiring up the Theme


So, do this. In /protected/config/main.php, set
'onBeginRequest'=>array('MyClass', 'BeginRequest'),
in /protected/components/ create a file MyClass.php like this:
class MyClass
{
  public function BeginRequest(CEvent $event)
  {
    Yii::app()->theme = Yii::app()->session['theme'];
  }
}
This will look for a theme name in the session. If it does not exist, Yii will use no theme (it will look like it does normally).

To switch themes, make a new controller. In /protected/controllers/ create BrowserController.php, and add this text:
class BrowserController extends Controller
{
    public function actionIndex($theme)
    {
      Yii::app()->session['theme'] = $theme;
      $referrer = Yii::app()->request->urlReferrer ? Yii::app()->request->urlReferrer : "/mob"; //or whatever your website root is
        Yii::app()->request->redirect($referrer);
    }
}
The above will take a theme name as a querystring parameter and put it in session, and redirect to either the HTTP Referrer or to the root of your site. You could also look for this directly in BeginRequest

To switch to the mobile theme, go to webroot/browser/mobile and to switch back go to webroot/browser/anythingelse