Allow array attributes with urlFormat path

What’s the problem?

When we configure CUrlManager::urlFormat to use ‘path’ it can handle URLs like




/name/john/gender/male

/status[]/open/status[]/closed

/status[7]/1/status[10]/1



The two last URLs contain one dimensional arrays and will be handled just fine. They will appear in $_GET like:




$_GET=array(

    'status'=>array( 7=>1, 10=>1),

);

But an URL like this will not get parsed right:


/User[status][]/10/User[status][]/20

The expected result in $_GET would be a ‘User’ array ready for mass assignment like this:




$_GET=array(

  'User'=>array(

    'status'=>array(10,20),

  )

)

Why does this matter?

I often use a setup like this (pseudo code):




Filter form (using $model as container for filter attributes):

<form method="get">

    Filter by name:

    <?php echo CHtml::activeTextBox($model,'name') ?>


    Filter by status:

    <?php echo CHtml::activeCheckBoxList($model,'status',$model->getStatusOptions()); ?>


    <input type="submit" value="Show filtered results">

</form>


Result in gridview:

<?php echo $this->widget('CGridView' array(

  'dataProvider'=>$model->search();

)); ?>



When you submit the filter form, the current page will reload with the $model form attributes in GET format as usual ($_GET[‘FilterForm’]=array(‘name’=>…)). The problem now arises from the pager in the grid view: It will create URLs that contain the current filter settings from $_GET - which is correct. These URLs now contain the model attributes in path format. If one of these attributes is an array (see ‘status’) you end up with an URL like in the example above.

What’s the solution?

To make this work CUrlManager::parsePathInfo() would need a change. First i thought, it should work with any depth of arrays:




/User[john][status][]/10/User[john][status][]/20 



But maybe that’s overkill, because this is a very sensible area (executed on every request) so the code should be very fast.

Is there a Workaround?

[b]

[/b]The only workaround i have now is to turn of ‘path’ format, before the grid view is rendered. But this affects all URLs created in the grid view, like links to a detail view. So it’s not really perfect.

EDIT:

I see there’s already a ticket for this:

http://code.google.com/p/yii/issues/detail?id=923

Cool, Qiang fixed this issue. Seems to work fine. Thanks!

http://code.google.com/p/yii/source/diff?spec=svn3100&r=3100&format=side&path=/trunk/framework/web/CUrlManager.php

The new CUrlManager version does not allow to use numeric keys in path / $_GET arrays, because array_merge_recursive does not respect numeric keys, so in the case when we have:




   'Model[25]/1/Model[27]/12'



Then resulting $_GET array will be




    array(

        'Model' => array('0' => '1', '1' => '12')

    )



Also I tried to replace array_merge_recursive with CMap::mergeArray($a, $b ) in the current CUrlManager version, but it also does not respects integer keys for the second ($b ) array.

In our current project we have several forms where we use numeric key to represent model id. And now these id’s are lost after url is parsed.

I am not sure whether this is a bug or we use wrong concept in our code and it should be refactored.

Anyway this change breaks BC, because the previous CUrlManager version worked.

You could open an issue i think.

Added a ticket - http://code.google.com/p/yii/issues/detail?id=2273