Statsburner

This PHP class is a wrapper for the Feedburner Awareness API. It grabs your circulation hits, views, stats and averages over a given period of time. Can be customized to grab data from certain dates, date ranges and discrete dates.

Proxy Search - Doing a search while using named parameters

Tuesday, March 31st 2009, 12:53am
Topics: Tutorials, CakePHP
Tags: CakePHP, Named, Params, Proxy, Search
Comments: 0
Permalink - Tinylink

While working on a project of mine, I wanted to be able to do a search, but have the post data be retained as named parameters (basically like a $_GET string). My first attempt was setting the form method to get, and trying to convert the $_GET by doing some mod_rewrite magic. This didn't work out at all, mainly because I couldn't get it to work for multiple named parameters. The only alternative I found was suggested by someone in the Google groups; they suggested posting a form to another action to deal with the logic, and finally redirect applying named parameters. This works perfectly, albeit adding an extra step in the process.

The process I created is something id like to call a Proxy Search. The following code should be placed in your app_controller.php file, so that it can be used as a global search by all controllers. You should not overwrite the proxy() action, unless you want specific logic in a certain controller.

/**
 * Sorts the named params for a posted page
 * @param string $model
 * @access public
 */
function proxy($model) {
	$data = array_map('urlencode', $this->data[Inflector::camelize($model)]);
	$referer = explode('/', trim($this->referer(), '/'));
	$router = array_merge(array('controller' => $referer[0], 'action' => $referer[1]), $data);
	
	$this->redirect($router);
}	

/**
 * Applies the named params to the controller data
 * @return array
 */
function _proxyGather() {
	return array_map('urldecode', $this->params['named']);
}


I will quickly try to explain how the form works. For example, if we are in the Users controller and want to do a search using the search() action, the forms url should point to /users/proxy/user instead of /users/search. Now shouldn't it be /users/proxy you ask? Well no, we need to know what model should be used in $data, so we need to pass an argument for the model that is used for the form (during $form->create()).

// UsersController::search()
echo $form->create('User', array('url' => array('controller' => 'users', 'action' => 'proxy', 'user')));

// If searching through books
echo $form->create('Book', array('url' => array('controller' => 'books', 'action' => 'proxy', 'book')));


Now back in the search() action, we need to grab the named params and pass them to the fields in the form. We do this by using the _proxyGather() method. No model name needs to be passed to _proxyGather(), simply because the data is pulled from the controller.

/**
 * Search players
 * @access public 
 */
function search() {
    $this->data['User'] = $this->_proxyGather();

    $this->pageTitle = 'Search Users';
    $this->set('results', $this->paginate('User'));
}


You can also have this interact with pagination quite easily. All you need to do is add some conditional logic in the controller, and pass the data to paginator.

/**
 * Search players
 * @access public 
 */
function search() {
    $this->data['User'] = $this->_proxyGather();
		
    if (!empty($this->data['User']['username'])) {
        $this->paginate['User']['conditions']['User.username LIKE'] = '%'. $this->data['User']['username'] .'%';
    }
    
    if (!empty($this->data['User']['firstName'])) {
        $this->paginate['User']['conditions']['User.firstName LIKE'] = '%'. $this->data['User']['firstName'] .'%';
    }

    $this->pageTitle = 'Search Users';
    $this->set('results', $this->paginate('User'));
}

// In the views using $paginator
$paginator->options(array('url' => $this->passedArgs));


I hope this has been helpful to someone who was looking to do a search system using named params, I know I had fun building it! I was thinking of turning this into a component, but have not figured out a way to do so yet, enjoy anyways!
Related Entries:

No Comments

10 / 2 = ?
Allowed: [code] [b] [i] [u]