Handle $_GET value overrides in ZF1 and PHP
Sometimes we have multiple select form elements and submitting these values via GET poses a server-side problem.
Consider this: mydomain.com/?cat=1&cat=12&cat=5
This is not a Zend Framework problem, its inherent to PHP, PHP’s internal storage for GCP $_GET,$_POST,$_COOKIE
works like arrays therefor
you cannot send duplicate request variable keys/names, as the latter will replace all previous values, see below:
<form method="get">
<select name="cat" multiple>
<option value="1" >Red</option>
<option value="12" >Blue</option>
<option value="5" >Blue</option>
</select>
<input type="submit" value="send">
</form>
<?php
/*With all 3 cat's values selected and submitted to the server,
it will be received as follows*/
$_GET['cat'] = 1;
$_GET['cat'] = 12;
$_GET['cat'] = 5; //cat now only has one value of 5, we've lost the other values
One solution is to change the multiple select to an array field name="cat[]"
and submit the form via POST.
Below is a solution I came up with to deal specifically with GET <?php $_GET ?>
for Zend Framework 1 – this method can also be used in vanilla PHP.
<?php
class CC_Controller_Request_Http extends Zend_Controller_Request_Http {
/**
* Retrieve an array of $_GET parameters with the same key name
*
* If no match is found an empty array is returned
* If the $key is an alias, the actual key aliased will be used.
*
* @param string $key
* @param array $default Default values to use if key not found
* @return array
*/
public function getParamMultiQuery($key, array $default = array())
{
$keyName = (null !== ($alias = $this->getAlias($key))) ? $alias : $key;
$query = $_SERVER['QUERY_STRING'];
$vars = array();
foreach (explode('&', $query) as $pair) {
list($qkey, $value) = explode('=', $pair);
if($qkey != $keyName || '' == trim($value)){
continue;
}
$vars[$qkey][] = urldecode($value);
}
return (count($vars)==0) ? array($keyName=>$default) : $vars;
}
/**
* Retrieve an array of all $_GET parameters by same key name
*
* @return array
*/
public function getParamsMultiQuery()
{
$query = $_SERVER['QUERY_STRING'];
$vars = array();
foreach (explode('&', $query) as $pair) {
list($key, $value) = explode('=', $pair);
if('' == trim($value)){
continue;
}
$vars[$key][] = urldecode($value);
}
return $vars;
}
}
<?php
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
protected function _initAppAutoload()
{
$moduleLoad = new Zend_Application_Module_Autoloader(array(
'namespace' => '',
'basePath' => APPLICATION_PATH
));
}
function _initApplication ()
{
$this->bootstrap('frontcontroller');
$front = $this->getResource('frontcontroller');
$front->setRequest('CC_Controller_Request_Http');
}
<?php
class CC_Controller_BaseController extends Zend_Controller_Action
{
/**
* Return an array of values matching 1 parameter in the
* {@link $_request Request object}
* grouped by the same $_GET name
*
* @param string $key
* @param array $default Default values to use if key not found
* @return array
*/
protected function _getParamMultiQuery($key, array $default = array())
{
return $this->getRequest()->getParamMultiQuery($key, $default);
}
/**
* Return an array of values matching all parameters in the
* {@link $_request Request object}
* grouped by the same $_GET name
*
* @return array
*/
protected function _getParamsMultiQuery()
{
return $this->getRequest()->getParamsMultiQuery();
}
}
Sample url for this controller: mydomain.com/search/?cat=1233&cat=44&cat=7866&foo=abc&bar=1&cat=32
<?php
class SearchController extends CC_Controller_BaseController
{
public function indexAction()
{
$allMultiVars = $this->_getParamsMultiQuery();
$multiCats = $this->_getParamMultiQuery('cat');
//echo '<pre>'; print_r($allMultiVars);
if(count($multiCats['cat'])){
$model = new Model_Products();
$data = $model->fetchAll('cats_id IN ('.implode(',', $multiCats).')');
}
Sample url for this controller: mydomain.com/search/?cat=1233&cat=44&cat=7866&foo=abc&bar=1&cat=3
<?php
class SearchController extends Zend_Controller_Action
{
public function indexAction()
{
$allMultiVars = $this->getRequest()->getParamsMultiQuery();
$multiCats = $this->getRequest()->getParamMultiQuery('cat');
//the standard ZF way
$allZf = $this->_getParams();
$zfCat = $this->_getParam('cat');
/*
* $zfCats will always only return 1 value,this is caused by PHP
* and not ZF.
* Optionally you can pass default array values if nothing is found
* $multiCats will be populated and returned
*/
$multiCats = $this->getRequest()->getParamMultiQuery('cat', array(233,55,1));
//echo '<pre>'; print_r($allMultiVars);
if(count($multiCats['cats'])){
$model = new Model_Products();
$data = $model->fetchAll('cats_id IN ('.implode(',', $multiCats).')');
}
Hope this helps someone!