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.

 

1: Create the below class and save it in your Library.

     <?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;
    }

}
      

2: Now add the lines 18,19, 20 to your Application Bootstrap file.

     <?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');

            }

3: Optionally you can now create a base Controller for all your Controllers, this is only for convenience and can be skipped.

     <?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();
    }
}

4.1: Usage, this is how you would access the Request object to retrieve multiple $_GET values. Use this method only if you applied step 3 with a base Controller.

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).')');
		}

4.2: Usage, this is how you would access the Request object to retrieve multiple $_GET values. Use this method if you applied step 3 with base Controller OR NOT.

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!