All posts tagged array

Override module config in Zend Framework 2

There is a time when you want to override module config in your Zend Framework 2 application. In my case, I have different configuration for SMS gateway in staging and live server. You can do this by overwriting the module.config.php file inside the module config’s folder. However, there are heaps of configuration inside module.config.php file. This approach will lead to maintenance nightmare when you need to change one or more configuration inside the file.

The cleanest approach is to override specific configuration key by creating module-name.local.php file inside config/autoload folder. For example, you have “Admin” module and here is the sample module.config.php file :

return array(
    'sms' => array(
        'username' => 'rudy', //API access username
        'password' => 'rudy', //API access password
        'sender' => 'Rudy', // max of 11 alphanumeric or max of 15 numerical characters
    ),
);

You can override only the username by creating admin.local.php file inside config/autoload folder and put this code inside it :

return array(
    'sms' => array(
        'username' => 'override', //API access username
    ),
);

Zend Framework 2 will read this file and overwrite the username key inside module.config.php. Now you can create script during your deployment process to create this file automatically.

Zend Framework 2 : The proper way to set application path in Javascript Object

Storing application path inside Javascript object is a way to avoid “hard coded” URL inside your Javascript file.  It is pretty common to have like this in your Javascript file :

$.ajax({
    type: POST,
    url: 'http://localhost/my-website/register',
    data: dataJSON
})

That approach is completely fine. However, when you need to deploy your application, you need to manually change all the URL to match with your server. The solution that I have been using for quite a long time is setting up Javascript object that contains path to my application.

In CakePHP, this can be easily done by using URL method inside Router Class. Here is the sample :

$cbunny = array(
    'APP_PATH' => Router::url('/',true)
);
echo $this->Html->scriptBlock('var CbunnyObj = ' . $this->Javascript->object($cbunny) . ';');

In Zend Framework 2, you have to rely on serverUrl and basePath to achieve the same thing. Here is the proper way to do it in Zend Framework 2 :

        <script type="text/javascript">
            //<![CDATA[
                var CMSObj = {
                    "APP_PATH":"<?php echo $this->serverUrl() . $this->basePath() ?>/"
                };
            //]]>
        </script>

 

Auto redirect in CakePHP jQuery AutoComplete

Demo : http://cbunny.rudylee.com/autocomplete_redirect

Demo source code : https://github.com/rudylee/cbunny

In my previous post ( http://blog.rudylee.com/2011/07/25/jquery-ui-autocomplete-in-cakephp/ ) we have successfully integrated the jQuery AutoComplete with CakePHP with a little bit hacky way. Now we gonna add another feature that can redirect user to our desired place when they click the result value in the AutoComplete ( try the demo for more details ).

So let’s start the coding ( I assume you have integrated the jQuery UI AutoComplete in your apps, if you haven’t, just read my previous post ), so basically what we need to do are divided into 4 steps:

  • Wrap the jQuery UI AutoComplete search field in a form tag.
  • Add a hidden field which will hold the ID of the result.
  • Add ‘select’ option into the helper.
  • Set up the action that will handle the form submit

Here is the sample of the action code:

[php] function admin_autoComplete() {
if (!empty($this->data)) {
$this->redirect(array(
‘controller’ => ‘users’,
‘action’ => ‘view’, $this->data['Guest']['id']
));
}
$this->autoRender = false;
$guests = $this->User->getGuests(array(
‘conditions’ => array(
‘OR’ => array(
‘User.name LIKE’ => ‘%’ . $_GET['term'] . ‘%’,
‘User.surname LIKE’ => ‘%’ . $_GET['term'] . ‘%’
)
)
));
echo json_encode($this->User->autoComplete_encode($guests));
}[/php]


Just ignore line 8 and so, we gonna focus on line 2 to 7. In that line, I redirect the user to the view action which based on the Guest ID which I got from the form. You can change the controller/action in this section. I hope everything are clear. Cheers.

jQuery UI AutoComplete in CakePHP

Demo : http://cbunny.rudylee.com/autocomplete

Demo source code : https://github.com/rudylee/cbunny
The post to add auto redirect feature into the AutoComplete : http://blog.rudylee.com/2011/12/12/auto-redirect-in-cakephp-jquery-autocomplete/
You can copy the modified Ajax and Javascript helpers from here https://github.com/rudylee/topping

Last week I was trying to use jQuery UI Autocomplete in my CakePHP apps. However, CakePHP Ajax and Javascript helpers don’t support jQuery by default. After googling a little bit, I found that this guy ( http://www.cakephp.bee.pl/ ) already made Ajax and Javascript helpers for jQuery.

So I just copied these helpers from his site and put it into my apps. It’s done ? obviously not. It turned out that the autocomplete script that he using in his helper is the old one ( http://docs.jquery.com/Plugins/autocomplete ).

Thus, I had to add a method inside that helper to use jQuery UI autocomplete. Here are the sample codes ( you can copy from my github for the complete file, this one is just snippet ) :

 /**
     * Options for auto-complete editor.
     *
     * @var array
     */
    var $autoCompleteOptions = array(
	'select', 'source'
    );

    /**
     * Create a text field with Jquery UI Autocomplete.
     *
     * Creates an autocomplete field with the given ID and options.
     * needs include jQuery UI Autocomplete file
     *
     * @param string $field DOM ID of field to observe
     * @param array $options Ajax options
     * @return string Ajax script
     * check out http://jqueryui.com/demos/autocomplete/
     */
    function autoComplete($field, $options = array()) {
	$var = '';
	if (isset($options['var'])) {
	    $var = 'var ' . $options['var'] . ' = ';
	    unset($options['var']);
	}

	if(isset($options['source'])) {
	    $options['source'] = "'".Router::url($options['source'])."'";
	}

	if (!isset($options['id'])) {
	    $options['id'] = Inflector::camelize(str_replace(".", "_", $field));
	}

	$htmlOptions = $this->__getHtmlOptions($options);
	$htmlOptions['autocomplete'] = "off";

	foreach ($this->autoCompleteOptions as $opt) {
	    unset($htmlOptions[$opt]);
	}

	$options = $this->_optionsToString($options, array('multipleSeparator'));
	$callbacks = array('formatItem', 'formatMatch', 'formatResult', 'highlight');

	foreach ($callbacks as $callback) {
	    if (isset($options[$callback])) {
		$name = $callback;
		$code = $options[$callback];
		switch ($name) {
		    case 'formatResult':
			$options[$name] = "function(data, i, max) {" . $code . "}";
			break;
		    case 'highlight':
			$options[$name] = "function(data, search) {" . $code . "}";
			break;
		    default:
			$options[$name] = "function(row, i, max, term) {" . $code . "}";
			break;
		}
	    }
	}
	$options = $this->_buildOptions($options, $this->autoCompleteOptions);

	$text = $this->Form->text($field, $htmlOptions);
	$script = "{$var} $('#{$htmlOptions['id']}').autocomplete(";
	$script .= "{$options});";

	return "{$text}\n" . $this->Javascript->codeBlock($script);
    }

And here are the sample to use it in our application

echo $this->Ajax->autoComplete('Guest.search', array(
    'source' => array(
	'controller' => 'users',
	'action' => 'autoComplete',
	'prefix' => 'host'
    ),
));

Action code :

 /**
     * Auto Complete Action for Host
     *
     * Auto Complete action for host list of guests
     * also process the search
     */
    function host_autoComplete() {
	if (!empty($this->data)) {
	    $this->redirect(array(
		'controller' => 'users',
		'action' => 'view', $this->data['Guest']['id']
	    ));
	}
	$this->autoRender = false;
	$guests = $this->User->getGuests(array(
		    'host_id' => Configure::read('User.id'),
		    'conditions' => array(
			'OR' => array(
			    'User.name LIKE' => '%' . $_GET['term'] . '%',
			    'User.surname LIKE' => '%' . $_GET['term'] . '%'
			)
		    )
		));
	echo json_encode($this->User->autoComplete_encode($guests));
    }

Model method ( encode the data array to display fields that we want, in this example I am just showing firstname and surname )

  /**
     * autoComplete encode
     *
     * Parsing passed array and change it to consume-able
     * by autocomplete jQuery UI
     * @param array $data
     * @return json $data
     */
    function autoComplete_encode($postData = array()) {
	$temp = array();
	foreach ($postData as $user) {
	    array_push($temp, array(
		'id' => $user['User']['id'],
		'label' => $user['User']['name'].' '.$user['User']['surname'],
		'value' => $user['User']['name'],
	    ));
	}
	return $temp;
    }

Don’t forget to use $_GET['term'] to get data from autocomplete field and also encode the data to JSON so it can be displayed by jQuery UI.