Expose Controller Methods

Bancha allows you to expose any CakePHP controller methods and then use it inside your Sencha Touch/Ext JS application. To expose a controller methods simply add the phpdocs @remotable to your method and inside the method return the result.

CakePHP Steps:

  1. Expose the method
    Simply add following phpdoc comment to the methods you want to expose:
    /**
     * @banchaRemotable
     */
  2. Define the result value
    The result will be the return value of the controller method. See also supported controller result-values.

Example

<?php
class UsersController extends AppController {

    /**
     * @banchaRemotable
     */
    public function getAnonymizedRecord($id = null) {

        // your business logic here
        $this->User->id = $id;
        if (!$this->User->exists()) {
            throw new NotFoundException(__('Invalid user'));
        }
        $user = $this->User->read(null, $id);
        $user['User']['firstname'] = '***';
        $user['User']['lastname'] = '***';

        // data for non-bacha requests
        $this->set('user', $user);

        // result for bancha requests
        return $user;
    }
}

Return Values

Bancha expects a exposed controller method to return a result. Bancha transforms controller the result to provide a better ease of use. The simplest result is a simple boolean, this will be transformed to the Sencha default format, an array with a success property. Here are all the possible return values:

Boolean Value

This indicates to Bancha that the operation was or was not successful, on the client side this will either trigger the failure or the success listener.

Bancha will transform this to the ExtJS/Sencha Touch response:

array(
    'success' => (boolean) $result
)

Single CakePHP Record

If you return a single record Bancha will transform it into the ExtJS/Sencha Touch structure. This is like it is used in the add or edit method.

A possible input looks like this:

array(
    'User' => array(
        'id' => 5,
        'name' => 'Joe',
    ),
)

You don’t have to clean this array from possible associated data, Bancha does this for you.

CakePHP Multi-Result

If you return a list of cake records Bancha will transform it into the ExtJS/Sencha Touch structure.

A possible input looks like this:

array(
    '0' => array(
        'User' => array(
            'id' => 5,
            'name' => 'Joe',
        ),
    ),
    '2' => array(
        'User' => array(
            'id' => 6,
            'name' => 'Roland',
        ),
    ),
)

You don’t have to clean this array from possible associated data, Bancha does this for you.

Paginated Result

This is a special structure, created by calling from inside the cake controller method:

return array_merge($this->request['paging']['_MODELNAME_'],
                           array('records'=>$queried_models));

We need this structure to map cakes paging properties to ExtJS/Sencha Touch. Bancha will scaffolld any CRUD index method like above to return a list of records to ExtJS/Sencha Touch stores.

Arbitrary Data

In this case you must provide a array with a success property, and Bancha will deliver the data as given.

A possible controller return value for this would be:

array(
    'success' => true // this is the only necessary property
    'data' => array( 'whatever' => true ),
    'message' => 'This is a optional message for the client.'
)

In all other cases Bancha will transform the data.

Returning error messages

If you want to return error messages create a return value like this:

array(
    'success' => false,
    'message' => 'By default this is shown to the user.'
);

Using methods with and without Bancha

You might want to use the same method in normal CakePHP requests (e.g. your frontend website) and in Bancha requests (e.g. your backend management area). This is perfectly possible, simply set view data for CakePHP requests (Bancha will ignore those) and provide a return value for Bancha requests.

If you want some specific behavior for Bancha, you can check for the isBancha flag on the request object:

if(isset($this->request->params['isBancha']) && 
	$this->request->params['isBancha']) {
	// Bancha specific behavior...
} else {
	// non-Bancha specific behavior...
}

Exceptions

In can happen that your CakePHP controller method throws an exception. You should not use exceptions as a way of messaging, instead use the success property to tell Sencha Touch/Ext JS that e.g. saving was not completed. Exceptions are only for debugging and handling of unexpected cases. It will always trigger the exception handling on the client side.

If CakePHP is in debug mode (debug level is 2), Bancha will output the whole exception including the exeption type and message. The default Bancha debug error handler will then show an Ext.Msg.alert with the thrown exception.

In production the server sends that an exception occured, but to protect the server against hackers no information about the exception is send. In production mode Bancha will also log the exception to the CakePHP error logs. You can disable this by adding Configure::write('Bancha.logExceptions', false); to your app/Config/core.php.

Keep in mind that the next time a server-request is generated Sencha Touch/Ext JS will try to re-transmit the failed request.

File Handling

Bancha also allows you to upload files. Since this is not possible with an XHR request Bancha requires the CakePHP method to also be marked with @formHandler. These methods can be used in forms as submit functions and will support uploading of files.

The uploaded file is available in the global $_FILES variable under the fieldname. A example usage can be found here:
Bancha Example code on GiHub

Redirects

A Bancha request will execute a CakePHP controller method and then transform the result value into a Ext JS/Sencha Touch response.

Since we require an immediate response there is now consistent way of handling redirects. Bancha requests should never execute an redirect, therefore if a redirect would happen, a BanchaRedirectException is thrown instead. In some cases you will need a redirect for normal CakePHP requests. The easiest way to handle this is to add conditional and provide an alternative behavior for Bancha requests:

if(isset($this->request->params['isBancha']) &&
	$this->request->params['isBancha']) {
	// handle Bancha request
	return $this->MyModel->computeSomeResult();
} else {
	// redirect CakePHP request
	$this->redirect(array('action' => 'index'));
}

Pluralization of Controller Names

CakePHP uses the pluralized version for controller names, so e.g. UsersController. Bancha in the frontend uses the singular version to match the Ext JS and Sencha Touch style. So you will use Bancha.getStub('User') in your JavaScript code.

If you have a special name with a different pluralization rule, or one that should never been pluralized you can tell CakePHP how to pluralize the name. So for example if you want to always keep YourBrand singular, add the following code to your app/Config/bootstrap.php:

Inflector::rules('plural', array('/^YourBrand$/i' => 'YourBrand'));

For more information about pluralization rules read the CakePHP documentation for Inflectors.

Comments

Add a comment