Noodlecode parody of spaghetti code

Month: June 2013

Database migration

Basic idea of database migration is database schema, which is organized into versions, need to be upgraded or downgraded from previous to current version. Refer to the diagram below, a simple database to store a blog post:

db_migration

On initial release (version 1), the application only have 4 columns – id, title, content & created. When new version come out (version 2), developer added two new columns – updated & cover_img.

For each version change, there must be upgrade() and downgrade() function. upgrade() is to upgrade the schema from previous to current version, while downgrade() is to revert changes to the previous version. Here’s how the upgrade & downgrade SQL queries going to be:

upgrade version 0 to 1

CREATE TABLE IF NOT EXISTS tbl_post (
  id INT NOT NULL AUTO_INCREMENT,
  title VARCHAR(255) NOT NULL,
  content TEXT NOT NULL,
  created DATETIME,
  PRIMARY KEY (id)
)

downgrade version 1 to 0

DROP TABLE tbl_post

upgrade version 1 to 2

ALTER TABLE tbl_post ADD (
  updated DATETIME,
  cover_img VARCHAR(255) NOT NULL
)

downgrade version 2 to 1

ALTER TABLE tbl_post
  DROP updated,
  DROP cover_img

To implement database versioning to support database migration, developer need to create a table to store information about the current database version that is in effect. It could be as simple as this table:

migration_tbl

New PHP

PHP is an amazing server side language to build web application. The ability to embed an executable code into text content is really practical in the web page generation, thus the most convenient language to use to create dynamic website. Additionally, it’s also easy to learn by beginner.

However, the language inconsistencies in naming, function output, default behavior etc. – is a real PITA to seasoned developers. One of the inconsistencies that I’d like to address here is the notation syntax used. Namespace declaration, variable name, methods and properties accessor & also array – they are all different. Some use backslash, some use arrow, some use double colon – as a result of borrowing syntax from a lot of other languages.

Therefore i hope in PHP 6 there’ll be some groundbreaking changes to its syntax. In my opinion, to be a much cleaner syntax, just use one format – dot notation. Here’s the new code syntax I suggest, together with some new features that I feel useful to have in new PHP

Current:

// namespace
namespace org\example\system;

use org\example\system\base;
use org\example\storage;
use org\example\collection\Dictionary;

// class
class Application extends baseApplication {

  private static $mode = 0;
  private $id = 0;
  private $db;

  public function __construct() {

    // method / property accessor
    $this->id = 1;
    $this->run();

    // namespaced class
    $this->db = new storageDatabase();
    $collection = new Dictionary(array('a','b'));

    // array
    $arr = array(
      'a' => 'A'
    );

    // array php 5.4
    $arr = [
      'b' => 'B'
    ];

    // array operation
    array_pop($arr);
    array_push($arr, 'c');

    // strings
    $str = 'name';
    $n = $str[0];
    $lower = strtolower($str);

    // include files
    require '../lib/functions.php';
    require_once '../lib/functions.php';
    include '../lib/functions.php';
    include_once '../lib/functions.php';

    // static method / property accessor
    $mode = self::$mode;
    $dict = Dictionary::create();

  }

  public function run() {

    // parent class accessor
    parent::run();

  }

}

New PHP:

// namespace
namespace org.example.system;

use org.example.system.base;
use org.example.storage;
use org.example.collection.Dictionary;

// class
class Application extends base.Application {

  private static mode = 0;
  private id = 0;
  private db;

  public function __construct() {

    // method / property accessor
    this.id = 1;
    this.run();

    // namespaced class
    this.db = new storage.Database();
    collection = new Dictionary(['a', 'b']);

    // array can be treated as mixed of hashed map,
    // dictionary, list or set
    // array is now an object type
    arr = [
      'b' : 'B'
    ];

    // array operation
    arr.pop();
    arr.push('c');
    arr[0];
    arr[0:2];
    arr[:2];

    // string is now object type,
    // not treated like an array
    str = 'name';
    str.charAt(0);
    str.substr(0, 1);
    str.toLower();

    // include files, use 'use' statement
    // all diff statement behavior will use 'include' behavior
    // use full path

    use com.example.lib.utils;
    use com.example.lib.functions as fn;

    // class alias
    fn.log('message');

    // static method / property accessor
    mode = self.mode;
    dict = Dictionary.create();

  }

  public function run() {

    // parent class accessor
    parent.run();

  }

}

Sure, it looks like Java (or Javascript, or Python), nothing wrong with that, as long as the primary feature – embeddable code – remain intact, PHP will always be the main choice for web app development.

Titanium ListView

Concept behind new Titanium ListView is similar to ModelViewViewModel (MVVM) pattern, where you have a set of data and you will map them to a view template

Let’s say you have this kind of data structure (model)

Person
- id {Number}
- name {String}
- photo {String} - URL
- message {String}

And you have an array of Person objects

var dataModels = [
  {
    id: 1,
    name: 'John',
    photo: 'http://example.com/img/john.jpg',
    message: 'Thank you'
  },
  {
    id: 2,
    name: 'Mary',
    photo: 'http://example.com/img/mary.jpg',
    message: 'Goodbye'
  },
  {
    id: 3,
    name: 'Chris',
    photo: 'http://example.com/img/chris.jpg',
    message: 'Hey there!'
  },
];

Now we want to map this array to a ListView, each Person object will use an ItemTemplate to produce a ListItem. First, define an ItemTemplate

var personTemplate = {
  childTemplates: [
    {
      type: 'Ti.UI.ImageView',
      bindId: 'photo',
      properties: {
        left: 5,
        top: 5,
        width: 50,
        height: Ti.UI.SIZE
      }
    },
    {
      type: 'Ti.UI.Label',
      bindId: 'name',
      properties: {
        left: 60,
        top: 5,
        height: 40,
        font: { fontSize: '18dp' },
        color: '#fff',
        wordWrap: false,
        ellipsize: true
      }
    },
    {
      type: 'Ti.UI.Label',
      bindId: 'message',
      properties: {
        left: 60,
        top: 45,
        font: { fontSize: '14dp' },
        color: '#eee'
      }
    }
  ]
};

A few things to note here. ItemTemplate defines views inside a ListItem, different from usual way we use add() method to add a view to another view. To compare how to define it with TableViewRow

var person = dataModels[i];
var row = Ti.UI.createTableViewRow({
  // to determine which row is being clicked
  itemId: person.id
});
row.add(Ti.UI.createImageView({
  image: person.photo,
  left: 5,
  top: 5,
  width: 50,
  height: Ti.UI.SIZE
}));
row.add(Ti.UI.createLabel({
  text: person.name,
  left: 60,
  top: 5,
  height: 40,
  font: { fontSize: '18dp' },
  color: '#fff',
  wordWrap: false,
  ellipsize: true
}));
row.add(Ti.UI.createLabel({
  text: person.message,
  left: 60,
  top: 45,
  font: { fontSize: '14dp' },
  color: '#eee'
}));

In childTemplates, is list of UI elements contain inside a ListItem. The way you define the element is by type & properties. bindId is the Person property (data model), which you want the UI to bind to – getting the data out and put it into the view.

Note that in Titanium documentation, there are ItemTemplate and ViewTemplate. ItemTemplate is used to generate a ListItem, while ViewTemplate is to generate other views, which specifically defined by the type property. See how to generate views in custom module, other than those defined in Ti.UI.* namespace.

However we cannot use dataModels array above directly onto ListView, we need to restructure it so it can be compatible with the UI element it is bound to. This process is called binding, which produce an array of view model (of type ListDataItem) that will be assigned to ListViewSection items property:

var viewModels = [
  {
    properties: { itemId: 1 },
    name: { text: 'John' },
    photo: { image: 'http://example.com/img/john.jpg' },
    message: { text: 'Thank you' }
  },
  {
    properties: { itemId: 2 },
    name: { text: 'Mary' },
    photo: { image: 'http://example.com/img/mary.jpg' },
    message: { text: 'Goodbye' }
  },
  {
    properties: { itemId: 3 },
    name: { text: 'Chris' },
    photo: { image: 'http://example.com/img/chris.jpg' },
    message: { text: 'Hey there!' }
  },
];

Notice that each Person properties have been changed, and by now it’s not considered data model any, but rather a view model. text and image are properties of Ti.UI.Label and Ti.UI.ImageView respectively, which you can use to bind the value to UI in the template you define earlier.

A ListView need to explicitly declare at least one ListSection, which acts as a place where you can set & append more ListItem.

var listView = Ti.UI.createListView({
  templates: {
    personTemplate: personTemplate
  },
  defaultItemTemplate: 'personTemplate'
});
var sections = [];
var section = Ti.UI.createListSection();
sections.push(section);
listView.setSections(sections);
win.add(listView);

You can add more template if you have more layout being used in a single ListView. Now load the dataSet into the ListView.

section.setItems(viewModels);

Load more items?

section.appendItems(viewModels);

Deeper visual tree of ItemTemplate

Use childTemplates on each UI element inside the template to customize it even more.

var personTemplate = {
  childTemplates: [
    {
      type: 'Ti.UI.ImageView',
      bindId: 'photo',
      properties: {
        left: 5,
        top: 5,
        width: 50,
        height: Ti.UI.SIZE
      }
    },
    {
      type: 'Ti.UI.View',
      properties: {
        layout: 'vertical',
        left: 60,
        top: 5
      },
      childTemplates: [
        {
          type: 'Ti.UI.Label',
          bindId: 'name',
          properties: {
            left: 0,
            top: 0,
            height: 40,
            font: { fontSize: '18dp' },
            color: '#fff',
            wordWrap: false,
            ellipsize: true
          }
        },
        {
          type: 'Ti.UI.Label',
          bindId: 'message',
          properties: {
            left: 0,
            top: 5,
            font: { fontSize: '14dp' },
            color: '#eee'
          }
        }
      ]
    }
  ]
};

Referring to template above, now you have this visual tree:

ListItem
 |__ ImageView
 |__ View
      |__ Label
      |__ Label

Events

For example, to add click event on image, add events property, specify an object with event name as key & callback as value

var template = {
  childTemplates: [
    {
      type: 'Ti.UI.ImageView',
      bindId: 'photo',
      properties: {
        left: 5,
        top: 5,
        width: 50,
        height: Ti.UI.SIZE
      },
      events: {
        click: function(e) {
          Ti.API.info('photo image clicked!');
        }
      }
    },{
      ...
    }
  ]
};

You can also use itemclick event of ListView to detect if a ListItem was clicked

listView.addEventListener('itemclick', function(e) {
  Ti.API.info('a ListItem was clicked!');

  // get which row is being clicked. See itemId property in viewModels above
  var person = dataModels.reduce(function(p, v) {
    if (v.id == e.itemId) {
      return v;
    }
    return p;
  });
});

Delete specific item from squid cache

If you want to delete specific item from squid cache, let’s say a cached JS or CSS file, this is the command

squidclient -m PURGE http://example.com/file/style.css

Run Windows Phone 8 emulator on VMware

wp8-emulator
This setup is using VMware Player 5.0.2

  1. Download Windows 8 pro 64-bit iso image with activator from http://tknowmore.blogspot.com/2013/05/windows-8-pro-x64-iso-direct-download-with-activator.html
  2. Install Windows 8. This should be straightforward since VMware Player 5 supports Windows 8.
  3. Install Windows Phone 8 SDK from http://developer.windowsphone.com/en-us/downloadsdk
  4. Edit VMware *.vmx config file. This will add configuration to avoid guest OS from realizing it is running on virtual machine.
    hypervisor.cpuid.v0 = "FALSE"

    vmx-file

  5. Enable virtualization emulation. In virtual machine settings,  go to ‘Hardware’ tab > Processors > Virtualization Engine. Then, select “Virtualize Intel VT-X/EPT or AMD-V/RVI”
    vmware-virtualization
  6. Open Visual Studio, create a new project & run on emulator
    run-on-emulator

Some notes:

  • emulator should be able to run
  • however, performance will be slow

Copyright © 2017 Noodlecode