phpcodeigniterurlcodeigniter-2

Holding array of values with CodeIgniter ruri_to_assoc()


I'm constructing a gallery which will use the URI to define a set of filter settings. CodeIgniter's ruri_to_assoc() works brilliantly for the majority of my settings as they are as simple as key=>value. However, one value (tags) can contain a number of values that I wish to match against.

As ruri_to_assoc() works off a key/val pairing, how would I set an array to a key in the url? Example:

/days/365/order/oldest/tag/car/tag/red/tag/mustang

At the moment, it looks like I'm going to have to explode the uri_string() and cycle through it myself. Like so:

$test_fil = explode('/',$this->uri->uri_string());
        unset($test_fil[0]);
        $val = 'key';
        foreach($test_fil as $fkey=>$fval){
            if($fval=='tags'){
                $val = 'tag';
                $new_filter['tags'] = '';
            }
            else{
                if($val == 'key'){
                    $new_filter[$fval] = '';
                    $val = 'val';
                    $current_key = $fval;
                }
                elseif($val == 'val'){
                    $new_filter[$current_key] = $fval;
                    $val = 'key';
                }
                else{
                    $new_filter['tags'][] = $fval;
                }

            }
        }

Is there something in CI that can do this for me?


Solution

  • We just need to make sure that uri_to_assoc will not override already existing keys when building the array.

    In application/core create MY_URI.php :

    class MY_URI extends CI_URI
    {
        protected function _uri_to_assoc($n = 3, $default = array(), $which = 'segment')
        {
            if ( ! is_numeric($n))
            {
                return $default;
            }
    
            if (isset($this->keyval[$which], $this->keyval[$which][$n]))
            {
                return $this->keyval[$which][$n];
            }
    
            $total_segments = "total_{$which}s";
            $segment_array = "{$which}_array";
    
            if ($this->$total_segments() < $n)
            {
                return (count($default) === 0)
                    ? array()
                    : array_fill_keys($default, NULL);
            }
    
            $segments = array_slice($this->$segment_array(), ($n - 1));
            $i = 0;
            $lastval = '';
            $retval = array();
    
            foreach ($segments as $seg)
            {
                /*HERE IS THE PART WE TRULY OVERRIDE*/
                if ($i % 2)
                {
                    if(is_array($retval[$lastval]))
                        $retval[$lastval][] = $seg;
                    else
                        $retval[$lastval] = $seg;
                }
                else
                {
                    if(isset($retval[$seg]) && !is_array($retval[$seg]))
                    {
                        $tmp = $retval[$seg];
                        $retval[$seg] = array();
                        $retval[$seg][] = $tmp;
                    }   
                    else if(!isset($retval[$seg]))
                    {
                        $retval[$seg] = NULL;
                        $lastval = $seg;
                    }
                }
                /*END OVERRIDE*/
    
                $i++;
            }
    
            if (count($default) > 0)
            {
                foreach ($default as $val)
                {
                    if ( ! array_key_exists($val, $retval))
                    {
                        $retval[$val] = NULL;
                    }
                }
            }
    
            // Cache the array for reuse
            isset($this->keyval[$which]) OR $this->keyval[$which] = array();
            $this->keyval[$which][$n] = $retval;
            return $retval;
        }
    }
    

    And then in your controller, nothing change :

    $myTags = $this->uri->uri_to_assoc();
    

    Here is what I get after testing :

    array (size=3)
      'days' => string '365' (length=3)
      'order' => string 'oldest' (length=6)
      'tag' => 
        array (size=3)
          0 => string 'car' (length=3)
          1 => string 'red' (length=3)
          2 => string 'mustang' (length=7)